计算所有连续子阵列的总和为零

时间:2014-10-23 16:22:37

标签: algorithm

给定长度为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)?

1 个答案:

答案 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())