传送门:腾讯2020校园招聘试题
1. 压缩算法
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 256M,其他语言512M
小Q想要给他的朋友发送一个神秘字符串,但是他发现字符串的过于长了,于是小Q发明了一种压缩算法对字符串中重复的部分进行了压缩,对于字符串中连续的m个相同字符串S将会压缩为m|S,例如字符串ABCABCABC将会被压缩为[3|ABC],现在小Q的同学收到了小Q发送过来的字符串,你能帮助他进行解压缩么?
输入描述:
输入第一行包含一个字符串s,代表压缩后的字符串。
S的长度<=1000;
S仅包含大写字母、[、]、|;
解压后的字符串长度不超过100000;
压缩递归层数不超过10层;
输出描述:
输出一个字符串,代表解压后的字符串。
输入例子1:
HG[3|B[2|CA]]F
输出例子1:
HGBCACABCACABCACAF
例子说明1:
HG[3|B[2|CA]]F −> HG[3|BCACA]F −> HGBCACABCACABCACAF
1.1 解题思路
这个题其实是括号匹配问题,是栈
的经典应用。解题思路如下:
(1)遍历输入字符串,如果不是右括号,则直接压栈;
(2)如果是右括号,则依次出栈直到弹出左括号,这里需要还原被压缩的子串,并压栈;
(3)最后取出栈中子串进行拼接得到结果。
1.2 Python代码
1 | string = input() |
2. 逛街
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 256M,其他语言512M
小Q在周末的时候和他的小伙伴来到大城市逛街,一条步行街上有很多高楼,共有n座高楼排成一行。
小Q从第一栋一直走到了最后一栋,小Q从来都没有见到这么多的楼,所以他想知道他在每栋楼的位置处能看到多少栋楼呢?(当前面的楼的高度大于等于后面的楼时,后面的楼将被挡住)
输入描述:
输入第一行将包含一个数字n,代表楼的栋数,接下来的一行将包含n个数字w_i(1<=i<=n),代表每一栋楼的高度。
1<=n<=100000;
1<=w_i<=100000;
输出描述:
输出一行,包含空格分割的n个数字vi,分别代表小Q在第i栋楼时能看到的楼的数量。
输入例子1:
6
5 3 8 3 2 5
输出例子1:
3 3 5 4 4 4
例子说明1:
当小Q处于位置3时,他可以向前看到位置2,1处的楼,向后看到位置4,6处的楼,
加上第3栋楼,共可看到5栋楼。当小Q处于位置4时,他可以向前看到位置3处的楼,
向后看到位置5,6处的楼,加上第4栋楼,共可看到4栋楼。
2.1 解题思路
这个题可以用动态规划的思想来解决,其方程如下:
i=0: dp[i] = 2 + dp_r[i+1]
i=n-1: dp[i] = 2 + dp_l[i-1]
i=[1,n-2]: dp[i] = 3 + dp_l[i-1] + dp_r[i+1]
dp[i]
表示当前位置能够看到的总楼栋数目,dp_l[i]
表示当前位置向前看到的楼栋数目,dp_r[i]
表示当前位置向后看到的楼栋数目。需要注意的是计算 dp_l 和 dp_r 的时候,是不包含当前楼栋的。
2.2 Python代码
1 | n = int(input()) |
3. 逆序对
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 256M,其他语言512M
作为程序员的小Q,他的数列和其他人的不太一样,他有 2n 个数。
老板问了小Q一共 m 次,每次给出一个整数 qi, 要求小Q把这些数每 2qi 分为一组,然后把每组进行翻转,小Q想知道每次操作后整个序列中的逆序对个数是多少呢?
例如:
对于序列1 3 4 2,逆序对有(4, 2),(3, 2), 总数量为2。
翻转之后为2 4 3 1,逆序对有(2, 1),(4, 3), (4, 1), (3, 1), 总数量为4。
输入描述:
第一行一个数n(0 <= n <= 20)
第二行2^n个数,表示初始的序列(1 <= 初始序列 <= 10^9)
第三行一个数m(1 <= m <= 10^6)
第四行m个数表示q_i(0 <= q_i <= n)
输出描述:
m行每行一个数表示答案。
输入例子1:
2
2 1 4 3
4
1 2 0 2
输出例子1:
0
6
6
0
例子说明1:
初始序列2 1 4 3
2^{q_1} = 2 ->
第一次:1 2 3 4 -> 逆序对数为0
2^{q_2} = 4 ->
第二次:4 3 2 1 -> 逆序对数为6
2^{q_3} = 1 ->
第三次:4 3 2 1 -> 逆序对数为6
2^{q_4} = 4 ->
第四次:1 2 3 4 -> 逆序对数为0
3.1 解题思路
这个题很容易被题目迷惑,最容易想到的方法是每次先将序列翻转后,再去求翻转序列的逆序对数目(关于求解逆序对数目的方法,可以参考这篇博客)。但是,这种做法的时间复杂度太高,无法通过所有的测试用例。
这里提供另外一种的思路,就是根据顺序对和逆序对之间的关系来求解。简单地说,原序列翻转后的逆序对数目,等于原序列的顺序对数目。比如:
原序列为:2, 1, 4, 3
顺序对有(2,4)、(2,3)、(1,4)、(1,3)共4对。
翻转后的序列为:3, 4, 1, 2
逆序对有(3,1)、(3,2)、(4,1)、(4,2)共4对。
因此,每次按照长度 k 翻转之后,其实只需要把长度不超过 k 的顺序对数目和逆序对数目交换,然后对长度不超过 k 的逆序对数目求和就得到总的逆序对数目。
3.2 Python代码
1 | def merge(nums, left_begin, left_end, right_begin, right_end, index, count): |
4. 假期
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 256M,其他语言512M
由于业绩优秀,公司给小Q放了 n 天的假,身为工作狂的小Q打算在在假期中工作、锻炼或者休息。他有个奇怪的习惯:不会连续两天工作或锻炼。只有当公司营业时,小Q才能去工作,只有当健身房营业时,小Q才能去健身,小Q一天只能干一件事。给出假期中公司,健身房的营业情况,求小Q最少需要休息几天。
输入描述:
第一行一个整数 n(1 <= n <= 10^5) 表示放假天数
第二行 n 个数 每个数为0或1,第 i 个数表示公司在第 i 天是否营业
第三行 n 个数 每个数为0或1,第 i 个数表示健身房在第 i 天是否营业
(1为营业 0为不营业)
输出描述:
一个整数,表示小Q休息的最少天数
输入例子1:
4
1 1 0 0
0 1 1 0
输出例子1:
2
例子说明1:
小Q可以在第一天工作,第二天或第三天健身,小Q最少休息2天
4.1 解题思路
首先我们定义小Q每天的状态如下:
-1: rest,在家休息
0: company,在公司工作
1: sports,在健身房锻炼
2: do any,在公司工作 或 在健身房锻炼
于是对于任意一天i
(注意要保证 i 的有效性),有下列的几种情况:
(1)如果第 i 天公司和健身房都营业:
a. 第 i-1 天去了公司,那么第 i 天就去健身房,状态为1
b. 第 i-1 天去了健身房,那么第 i 天就去公司,状态为0
c. 第 i-1 天在家,那么第 i 天就可以去健身房或去公司,状态为2
(2)如果第 i 天只有公司营业:
a. 第 i-1 天没有去公司,那么第 i 天就去公司,状态为0
b. 第 i-1 天可能去了健身房或公司,若第 i-2 天没有去公司,那么第 i 天就去公司,状态为0
(3)如果第 i 天只有健身房营业:
a. 第 i-1 天没有去健身房,那么第 i 天就去健身房,状态为1
b. 第 i-1 天可能去了健身房或公司,若第 i-2 天没有去健身房,那么第 i 天就去健身房,状态为1
4.2 Python代码
1 | n = int(input()) |
5. 视野争夺
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 256M,其他语言512M
小Q在进行一场竞技游戏,这场游戏的胜负关键就在于能否能争夺一条长度为L的河道,即可以看作是[0,L]的一条数轴。
这款竞技游戏当中有n个可以提供视野的道具−真视守卫,第i个真视守卫能够覆盖区间[xi,yi]。现在小Q想知道至少用几个真视守卫就可以覆盖整段河道。
输入描述:
输入包括n+1行。
第一行包括两个正整数n和L(1 <= n <= 10^5, 1 <= L <= 10^9)
接下来的n行,每行两个正整数x_i,y_i(0 <= x_i <= y_i <= 10^9), 表示第i个真视守卫覆盖的区间。
输出描述:
一个整数,表示最少需要的真视守卫数量, 如果无解, 输出-1。
输入例子1:
4 6
3 6
2 4
0 2
4 7
输出例子1:
3
5.1 解题思路
这是一个区间覆盖问题,解决这类问题的步骤如下:
(1)首先对区间进行从小到大排序(按照左边界排序,若左边界相同则对右边界排序);
(2)判断排序后区间的最小左边界
和最大右边界
能否覆盖整段河道,如果不能则无解;
(3)在确定有解的情况下,每次遇到有效区间
(该区间与已经能够覆盖的区间有交集)的时候,需要判断该区间是否能取代上一个有效区间,如果可以取代则更新能够覆盖的区间,如果不能取代则丢弃该区间:
a. 上一个有效区间是该区间的子集,即该区间虽然左边界相同,但右边界更大;
b. 该区间与上一个有效区间产生交集,移除上一个有效区间后,若该区间仍然是有效区间则循环继续移除前面的有效区间,直到该区间无效循环停止(注意此处需要还原最后一个移除的有效区间,然后添加该区间);
(4)在遍历处理每个区间的时候,如果当前的有效区间已经能够覆盖整个河道,则需提前停止遍历。
5.2 Python代码
1 | n, L = input().split() |

...
...