数字序列比大小
- A、B两人一人一个整数数组,长度相等,元素随即;
- 两人随便拿出一个元素(弹出),比较大小,赢的得一分,输的减去一分,否则分值都不变;
- B每取一个元素都明示,求A赢B时的最大分值;
输入:
n 数组长度
arr1
arr2
输出:
求A赢B时的最大分值
示例1
输入:
3
4 8 10
3 6 4
输出:
3
示例2
输入:
4
3 6 2 10
2 5 7 11
输出:
3
思路:
- 对两个数组排序,并使用一个flag表示A 有能赢B 的元素;
- arr_b弹出第一个值,arr_a中取能赢arr_b的最小值;
- score_a 累加1;
- 示例可以找arr_a排序后元素全小于arr_b;全大于arr_b;有大于有小于arr_b;
python:
n = int(input().strip())
arr_a = list(map(int, input().strip().split()))
arr_b = list(map(int, input().strip().split()))
arr_a.sort()
arr_b.sort()
score_a = score_b = 0
flag = True # 表示A能赢B
while flag and arr_b:
flag = False
e_b = arr_b.pop(0)
i = 0
# 取保证A赢的最小元素
while i < len(arr_a) and arr_a[i] <= e_b: # 只有大于才算赢
i += 1
if i < len(arr_a):
flag = True
arr_a.pop(i)
score_a += 1
score_b -= 1
print(score_a)
最佳植树距离
- 给定一些适合种树的坐标点和树苗数量;
- 让树苗均匀分开,确定最佳的种树距离;
示例1
输入:
7 坐标的数量
1 5 3 6 10 7 13 坐标
3 树苗数量
输出:
6 最佳的植树距离
思路:
- coords坐标数组升序排序;
- 植树距离最小为1,最大max_dist为【最大坐标-最小坐标】;
- for dist in range(1, max_dist+1);
- for i in range(coords[0], coords[-1]+1, dist):
- used_trees += 1 并且保存植树的坐标位置
- used_tree > has_tree continue;
- used_tree == has_tree 判断是否合法坐标;
- used_tree < has_tree 距离太大 break
python:
coord_n = int(input().strip())
coords = list(map(int, input().strip().split()))
coords.sort()
trees_m = int(input().strip())
find_best_dist = False
max_dist = coords[-1] - coords[0]
dist = 1
for dist in range(1, max_dist+1):
used_trees = 0
pos_list = []
for i in range(coords[0], coords[-1] + 1, dist):
used_trees += 1
pos_list.append(i)
if used_trees > trees_m: # 说明当前间距太小
continue
elif used_trees == trees_m:
# 如果当前位置都是有效位置,且以均匀种植完所有的树苗,则break
if all([True if i in coords else False for i in pos_list]):
find_best_dist = True
break
else:
break
if find_best_dist:
print(dist)
else:
print(-1)
文艺汇演
- 一个人只能观看一场演出,不能迟到、早退;
- 连续观看的演出至少有15分钟的间隔;
- 根据时间表,计算最多可以看几场演出;
示例1
输入:
2 演出场数
720 120 开始时间-持续时间
840 120 开始时间-持续时间
输出:
1
示例2
输入:
5
20 120
80 120
130 70
140 60
200 50
输出:
2
示例3
输入:
4
20 200
30 30
50 45
110 60
输出:
2
思路:
- 动态规划
- 所有场次按照开始时间升序排序
- 后一场的开始时间与前一场的结束时间比较,是否有15分钟的间隔;
- 有则可以看,取后面这一场的结束时间,作为后续比较;
- 间隔不足,则选择看结束时间最早的那一场,刷新结束时间;
python:
def calc_max_plays(arr):
global n, can_see_num
if n == 1: # 场次是>=1
return
# 结束时间
end_time = arr[0][0] + arr[0][1]
cur = 1
while cur < n:
if arr[cur][0] - end_time >= 15:
# 可以看 则刷新结束时间
can_see_num += 1
end_time = arr[cur][0] + arr[cur][1]
else:
# 选择场次(最早结束的场次)
end_time = min(end_time, arr[cur][0] + arr[cur][1])
cur += 1
return
if __name__ == '__main__':
# 所有场次数
n = int(input().strip())
plays = []
for i in range(n):
start_last = list(map(int, input().strip().split()))
plays.append(start_last)
# 按照开始时间排序
plays = sorted(plays, key=lambda i:i[0])
print(plays)
can_see_num = 1
# 计算最多场次
calc_max_plays(plays)
print(can_see_num)
计算误码率
- 误码率 = 错误比特数 / 总比特数;以字符串表示总位数,错误字符数,即为错误比特数;
- 字符串会被压缩,如2A3B4D5X 表示“AABBBDDDDXXXXX”;
- 第一次输入原始的压缩字符串,第二次输入出错的压缩字符串;
- 解压后两个字符串长度相等,计算误码率;
示例1
输入:
3A3B
2A4B
输出:
1/6
示例2
输入:
5Y5Z
5Y5Z
输出:
0/10
示例3
输入:
4Y5Z
9Y
输出:
5/9
思路:
- 还原字符串,并逐一对比,统计所有字符个数和错误字符个数;
- 输出误码率比例;
python:
s1 = "5Y5Z"
s2 = "5Y5Z"
s1_restore = ""
s2_restore = ""
s1_char_num = 0
for i in s1:
if i.isdigit():
s1_char_num = int(i)
else:
s1_restore += i * s1_char_num
s2_char_num = 0
for i in s2:
if i.isdigit():
s2_char_num = int(i)
else:
s2_restore += i * s2_char_num
# 两者恢复后长度相等
n = len(s1_restore)
error_num = 0
for i in range(n):
if s1_restore[i] != s2_restore[i]:
error_num += 1
print(f"{
error_num}/{
n}")
二维伞的雨滴效应
- 输入一个正整数数组,无0,无重复,数组最小长度为1;
- 判断是否为二叉排序树,是则输出1,并输出左右子树的叶子节点值;
- 不是二叉排序树,则输出0 0 0,中间空格分隔;
示例:
输入:
8 3 1 6 4 7 10 14 13
输出:
1 1 13
思路:
- 构造二叉搜索树,前序遍历结果与数组对比,一致则数组为二叉搜索树的前序遍历结果;
- 前序遍历,最后一个数是最右侧叶子节点;
- 中序遍历,第一个节点为最左侧叶子节点;
python:
class TreeNode(object):
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
# 构造二叉排序树
def insert_node(root, val):
if root is None:
return TreeNode(val)
if val > root.data:
# 右边插入
root.right = insert_node(root.right, val)
else:
root.left = insert_node(root.left, val)
return root
# 中序遍历
# 左子树、root、右子树
if __name__ == '__main__':
# 构造二叉树排序树
alist = [8, 3, 1, 6, 4, 7, 10, 14, 13]
root = None
for i in alist:
root = insert_node(root, i)
root2 = root
in_order_list = []
# 中序遍历
stack = []
while root or stack:
while root:
in_order_list.append(root.data)
# 根节点入栈
stack.append(root)
root = root.left
root = stack.pop()
root = root.right
output_list = []
if alist == in_order_list:
output_list.append(1)
# 中序遍历 获取最左侧的叶子节点
pre = None
while root2:
pre = root2
root2 = root2.left
output_list.append(pre.data if pre.right is None else 0)
# 前序获取最右边叶子节点
output_list.append(in_order_list[-1])
else:
output_list = [0, 0, 0]
print(output_list)
阿里巴巴找黄金宝箱4
- 有0-N个箱子排成一个环,每个箱子有自己对应的编号;
- 输出每一个箱子后第一个比自己编号大的数;
- 多个数以,分隔输出;
示例1:
输入:
2,5,2
输出
5,-1,5
示例2:
输入:
3,4,5,6,3
输出
4,5,6,-1,4
思路:
- 数组复制一份,拼接在一起;
- 单调栈,从栈顶到栈底,递增为单调递增栈;否则为单调递减栈;
- 单调栈解决大小关系;这里用于存储arr的索引
python:
if __name__ == '__main__':
arr1 = list(map(int, "3,4,5,6,3".split(",")))
n = len(arr1)
# 存储比0-n对应位置大的第一个数
arr2 = [-1 for i in range(n)]
# 单调栈
stack = []
# 双份数组
double_arr = arr1 + arr1
for i in range(2*n):
cur_data = double_arr[i]
while stack and cur_data > arr1[stack[-1]]:
# 找到当前比idx处大的第一个数
cur_idx = stack.pop()
arr2[cur_idx] = cur_data
if i < n:
# 索引入栈
stack.append(i)
arr2_str = map(str, arr2)
print(",".join(arr2_str))
java
import java.util.Scanner;
import java.util.*;
import java.lang.Integer;
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] nums = Arrays.stream(sc.nextLine().split(",")).mapToInt(Integer::parseInt).toArray();
int len = nums.length;
//将数组复制成双份数组([1,2,3] -> [1,2,3,1,2,3])
int[] doubleNums = Arrays.copyOf( nums, len *2);
System.arraycopy( nums, 0, doubleNums, len, len);
//各位置对应第一个比他大的数
int[] resInts = new int[len];
//初始化为 -100001,因为宝箱数值范围 >= -100000,<=100000
Arrays.fill( resInts, -100001);
Deque<Integer> deque = new ArrayDeque<>();
for(int i=0; i<len*2; i++){
int num = doubleNums[i];
System.out.println("55--" + num);
//单调栈
while (!deque.isEmpty() && num > nums[deque.peek()]){
// deque.peek() 访问栈顶
//双向队列中有值,且最后一个值小于当前数字则取出
//并通过队列中的索引,对 resInts 进行赋值
System.out.println("出队" + num);
int index = deque.pop(); // 弹出栈顶
resInts[index] = num;
}
if(i < len){
System.out.println("入队" + i);
deque.push(i);
}
}
String res = "";
for(int i : resInts){
if(i == -100001){
//等于 -100001 说明不存在,则输出 -1
i = -1;
}
res += i + ",";
}
System.out.println(res.substring( 0, res.length() - 1));
}
}
 ;
树状结构查询
- 输入节点组合的行数n;
- n行中每行是(子节点 父节点)的组合;
- 最后一行输出 要查询的节点;
- 输出该查询节点的所有子节点;
示例
输入:
5
b a
c a
d c
e c
f d
c
输出:
d
e
f
思路:
- 哈希存储根节点、子树的根节点;
- 广度搜索 + 递归;
python实现:
def output_ch(node):
global root_dict, result_nodes
chs = root_dict.get(node)
if chs is None:
return
result_nodes += chs
for node in chs:
output_ch(node)
if __name__ == '__main__':
n = int(input())
root_dict = {
}
for i in range(n):
ch, root = input().strip().split()
if root in root_dict:
root_dict[root].append(ch)
else:
root_dict[root] = [ch]
# 要查询的节点
target_ch = input().strip()
# 输出查询节点的所有子节点
result_nodes = []
output_ch(target_ch)
# 字典序排序
result_nodes.sort()
for i in result_nodes:
print(i)
人气最高的店铺
- 输入n个市民,m个店铺,每个市民只能为一个店铺投1票;
- 1号店铺发放q元的金额补贴,可以让某市民为其投1票;
- 计算1号店铺至少发放多少补贴,才可以人气最高。
示例1
输入:
5,5 市民数和店铺数
2,10 投票意向(1-m)改投1号店需要的补贴金额
3,20
4,30
5,40
5,90
输出:
50
思路:
- 每组投票及补贴,按照需要的补贴金额从小到大排序;
- 统计每个商铺的票数;
- get_vote()函数,如果当前排名1店铺人气最高,则return min_cost;
-否则,从补贴成本最小的票中拉一票;更新相应商铺的票数,再递归调用get_vote() - 待优化
python:
# 5,5
# 2,10
# 3,20
# 4,30
# 5,40
# 5,90
def get_vote(shop_votes, votes_list):
global min_cost
# 当前人气排名
current_rand = sorted(shop_votes.items(), key=lambda i:i[1], reverse=True)
if current_rand[0][0] == 1 and current_rand[0][1] > current_rand[1][1]:
return min_cost
temp_vote = votes_list.pop(0)
cur_shope = temp_vote[0]
shop_votes[cur_shope] -= 1
# 票数 +1
shop_votes[1] += 1
# 成本 +q
min_cost += temp_vote[1]
return get_vote(shop_votes, votes_list)
if __name__ == '__main__':
n, m = list(map(int, input().split(",")))
votes = []
shop_votes = {
}
for i in range(n):
temp = list(map(int, input().strip().split(",")))
if temp[0] in shop_votes:
shop_votes[temp[0]] += 1
else:
shop_votes[temp[0]] = 1
votes.append(temp)
votes = sorted(votes, key=lambda i:i[1])
if 1 not in shop_votes:
shop_votes[1] = 0
min_cost = 0
origin_votes_list = votes.copy()
get_vote(shop_votes, origin_votes_list)
print(min_cost)
采样过滤
pass
最节约的备份方法
pass