作者:晓宜
个人简介:互联网大厂Java准入职,阿里云专家博主,csdn后端优质创作者,算法爱好者
上周末参与了滴滴的春招笔试,第一题是差分数组的改版题,但是测试数据不强,听同学说暴力遍历也能过,whatever,这里分享下两种解法,顺便讲解下差分数组
❤️❤️❤️
你的关注是我前进的动力
小明正在模拟陨石对地质的危害。在小明的模型下,将地面从0,1,2…直到N依次从左到右进行标号。每次陨石i坠落,会使得标号在[L,R]这个区间范围内的地面受到一次陨石打击。
在 M 次陨石坠落后,小明想知道某些指定地面在刚才 M 次陨石坠落中受到了多少次陨石打击。
第一行两个正整数 N,M,含义如题面,
接下来一行 M 个数,分别为L1,L2,…,Ln表示这M次陨石打击的左边界。
接下来一行 M 个数,分别为R1,R2,…,Rn,表示这M次陨石打击的右边界。
接下来一个数 Q,表示小明询同次数。
接下来一行Q个数x,表示小明想知道标号为x的地面在刚才M次阳石坠落中受到了多少次打击。
输出一行 Q 个数,用空格隔开(无行未空格),分别表示每次询问的答案。
示例:
4 3
1 2 2
2 3 4
5
0 1 2 3 4
0 1 2 3 4
我们先介绍一种朴素的思想,对于每一次陨石掉落,我们把那个区间所有的数都加1,在查询阶段直接返回这个数的值。
这么做显然是正确的,但是考虑到每一次输入都要遍历特定区间,这么做的时间复杂度是 o ( n 2 ) o(n^2) o(n2)
在笔试中可以考虑先把这种写法实现,看看过了多少测试用例,就本题目而言,这种暴力法可以ak。
N,M = map(int,input().split(" "))
left = [int(v) for v in input().split(" ")]
right = [int(v) for v in input().split(" ")]
ans = [0 for i in range(N+1)]
for i in range(M):
for j in range(left[i],right[i]+1):
ans[j] += 1
q = int(input())
x = [int(v) for v in input().split(" ")]
for i in x:
print(ans[i],end = " ")
我们可以优化上述逻辑中的每次输入给这一区间中所有数加1的这一逻辑,具体做法如下:
N,M = map(int,input().split(" "))
left = [int(v) for v in input().split(" ")]
right = [int(v) for v in input().split(" ")]
dif = [0 for i in range(N+2)]
for i in range(M):
dif[left[i]] += 1
dif[right[i]+1] -= 1
ans = []
cur = 0
for i in range(N+2):
cur += dif[i]
ans.append(cur)
q = int(input())
x = [int(v) for v in input().split(" ")]
for i in x:
print(ans[i],end = " ")