给定长度为n的随机数(正数和负数)数组,我想要数量连续的子数组,其总和等于零。
示例:
鉴于我有数组a={1, -1 ,2 , -2, 6, -6}
,输出将为6
,因为子数组如下所示:
1 -1 & 2 -2 & 6 -6 & 1 -1 2 -2 & 2 -2 6 -6 & 1 -1 2 -2 6 -6
我知道蛮力解O(n ^ 2),我想要任何其他解O(n)或O(n log n)?
答案 0 :(得分:9)
让数组为a1,...,an。设s0,...,sn为由sj = a1 + ... + aj(和s0 = 0)定义的前缀和。从i到j包含的子阵列的总和是sj-si-1。对于O(n)/ O(n log n)时间算法,使用映射,计算前缀和中每个数字的出现次数。总和k在此地图的值中为k选择2。
例如,如果我们有你的数组
1 -1 2 -2 6 -6
然后前缀总和是
0 1 0 2 0 6 0
并且计数
0: 4
1: 1
2: 1
3: 1
输出为4选2 + 1选2 + 1选2 + 1选2 = 6(其中k选2 = k(k-1)/ 2)。
在Python中:
def countsumzero(lst):
prefixsums = [0]
for x in lst:
prefixsums.append(prefixsums[-1] + x)
freq = {}
for y in prefixsums:
if y in freq:
freq[y] += 1
else:
freq[y] = 1
return sum(v*(v-1) // 2 for v in freq.values())