给定一组N个正整数。它可以有n*(n+1)/2
个子数组,包括单个元素子数组。每个子数组都有一个总和S
。对于所有子阵列,查找S's
显然为O(n^2)
,因为子阵列的数量为O(n^2)
。许多总和S's
也可能重复。有没有办法在O(n logn)
中找到所有不同总和的计数(不是总和的确切值,只是计数)。
我尝试了一种方法,但坚持不懈。我将数组从索引1迭代到n
假设a[i]
是给定的数组。对于每个索引i
,a[i]
将添加a[i-1]
所涉及的所有总和,并将其自身也包含为单个元素。但是如果在涉及a[i-1]
的总和中,两个总和的差异为a[i]
,则会出现重复。我的意思是,总和Sp
和Sq
最终为a[i-1]
,两者的差异为a[i]
。然后Sp + a[i]
等于Sq
,将Sq
作为副本。
说C[i]
是结束于a[i]
的不同总和的计数
所以C[i] = C[i-1] + 1 - numbers of pairs of sums in which a[i-1] is involved whose difference is a[i]
。
但问题是在O(log n)
中找到对数的一部分。请给我一些关于此的提示,或者如果我的方法不对,需要完全不同的方法问题请指出。
答案 0 :(得分:10)
当S不太大时,我们可以用一个(快速)多项式乘法来计算不同的和。当S较大时,N有望小到足以使用二次算法。
设x_1,x_2,...,x_n为数组元素。设y_0 = 0且y_i = x_1 + x_2 + ... + x_i。令P(z)= z ^ {y_0} + z ^ {y_1} + ... + z ^ {y_n}。计算多项式P(z)* P(z ^ { - 1})的乘积; z> k的系数,其中k>当且仅当k是子阵列和时,0是非零的,所以我们只需要读取正幂的非零系数的数量。此外,z的幂在-S到S的范围内,因此乘法在S log S的顺序上花费时间。
答案 1 :(得分:0)
您可以将子数组视为一种树。从某种意义上说,子阵列[0,3]
可以分为[0,1]
和[2,3]
。
因此构建一个树,其中节点由子数组的长度定义,并且它在原始数组中保持偏移,并且每当计算子数组时,将结果存储在此树中。
计算子数组时,可以检查此树是否有现有的预先计算的值。
此外,在划分时,如果重要的话,可以在不同的CPU内核上计算部分数组。
此解决方案假设您不需要同时使用所有值,而是临时。 对于前者,可能会有一些更智能的解决方案。
另外,我假设我们正在谈论10000多个元素的计数。否则,这样的工作是一个很好的练习,但没有多大实际价值。