计算所有 k 乘积之和的高效算法
假设给您一个由 n
个数字组成的列表 L
和一个整数 k
L
中k
个不同数字的所有乘积之和?
以 L=[1,3,4,6]
和 k=2
为例。那么我要查找的数字是
1*3 + 1*4 + 1*6 + 3*4 + 3*6 + 4*6
。
你能想出一种方法来避免生成所有大小为 k 的子集吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
令 F(X,k,n) 为数组 X 的前 n 个元素的 k 乘积和。
F(X,k,n) = F(X,k,n-1)+F(X,k-1) ,n-1)*X[n]
您可以使用动态规划来解决。复杂度 = O(kn)。
F(X,k,n) 的结束条件: 当 n=k F(X,k,k) = X[1]* X[2]*...*X[n]
更多详细信息:
Let F(X,k,n) be the k-product sum of first n elements of array X.
F(X,k,n) = F(X,k,n-1)+F(X,k-1,n-1)*X[n]
which you can solve using dynamic programming. Complexity = O(kn).
End conditions for F(X,k,n): When n=k F(X,k,k) = X[1]* X[2]*...*X[n]
More details:
是的,有办法。考虑多项式
它的系数只是
k
乘积的总和,其次数为n
,因此您可以计算所有k
的总和-在 O(n^2) 步中同时计算所有k
的产品。经过
s
步后,Xsk的系数是第一个s
数组的k
乘积之和元素。前s+1
元素的k
乘积分为两类,涉及(s+1)
st< /sup> 元素 - 这些具有形式a[s]*((k-1)
- 第一个s
元素的乘积) - 以及那些不涉及它的 - 这些是第一个的 k 个乘积s
元素。代码使得
result[i]
是 Xi 的系数((ni)
-乘积之和):如果您只想一个
k
的k
乘积之和,您可以在索引nk
处停止计算,给出 O(n*(nk) ) 算法 - 如果k >= 就很好n/2
。要获得k <= n/2
的 O(n*k) 算法,您必须以相反的方式组织系数数组,以便result[k]
是 Xnk 的系数(如果您只需要一个和,则在索引k
处停止计算):Yes, there is a way. Consider the polynomial
Its coefficients are just the sums of the
k
-products, its degree isn
, so you can calculate the sum of allk
-products for allk
simultaneously in O(n^2) steps.After
s
steps, the coefficient of Xs-k is the sum of thek
-products of the firsts
array elements. Thek
-products of the firsts+1
elements fall into two classes, those involving the(s+1)
st element - these have the forma[s]*((k-1)
-product of the firsts
elements) - and those not involving it - these are thek
-products of the firsts
elements.Code such that
result[i]
is the coefficient of Xi (the sum of the(n-i)
-products):If you only want the sum of the
k
-products for onek
, you can stop the calculation at indexn-k
, giving an O(n*(n-k)) algorithm - that's good ifk >= n/2
. To get an O(n*k) algorithm fork <= n/2
, you have to organise the coefficient array the other way round, so thatresult[k]
is the coefficient of Xn-k (and stop the calculation at indexk
if you want only one sum):您可以探索的一个有趣的属性是乘法相对于加法的分配属性。
当 k = 1 时,这是微不足道的:
当 k = 2 时:
当 k = 3 时,事情会变得更有趣:
对于 k = 4: 对于
较大的 n 值,这应该成立。
C# 中的实现:
可以通过记忆进一步改进。
An interesting property you could explore is the distributive property of multiplication in relation to addition.
When k = 1, it's trivial:
When k = 2:
When k = 3, things get a bit more interesting:
And for k = 4:
This should hold for larger values of n.
An implementation in C#:
Which can be further improved by memoization.
您可以将 k 减少 1:
例如,对于 k=2
==
和 k=3
==
所以基本上您循环列表,然后递归到相同的算法,其中 k 减少 1 并且仅列表的其余部分
You can reduce k by 1:
e.g. for k=2
==
and for k=3
==
So basically you cycle your list, then recurse to the same algorithm with k reduced by 1 and only the rest of the list
对于 k=2,
让我们
s = SUM_x_in_L x
(数字之和)和sq = SUM_x_in_L x^2
(平方和),那么它就是
SUM_x_in_L ( s - x) * x / 2 = (s * s - sq) / 2
For k=2,
let's
s = SUM_x_in_L x
(sum of the numbers) andsq = SUM_x_in_L x^2
(sum of the squares)then it's
SUM_x_in_L (s - x) * x / 2 = (s * s - sq) / 2
从代数角度来说,对于
k=2
,只需取L
的元素之和,平方,然后减去L
的平方和。也就是说:在您的示例中,您正在计算的是这个
这应该会提示您一般如何进行。
Algebraically, for
k=2
just take the sum of the elements ofL
, square it, and subtract the sum of the squares ofL
. That is:In your example, what you are computing is this
This should give you a hint for how to proceed in general.