计算n的值选择k

时间:2013-03-08 19:35:35

标签: algorithm language-agnostic combinations

评估n选择k值的最有效方法是什么? 我认为蛮力方式是找到n阶乘/ k阶乘/(n-k)阶乘。

更好的策略可能是根据此recursive formula使用dp。有没有其他更好的方法来评估n选择k?

8 个答案:

答案 0 :(得分:40)

这是我的版本,它纯粹用整数运算(除以k总是产生一个整数商),并且在O(k)处快速运行:

function choose(n, k)
    if k == 0 return 1
    return (n * choose(n - 1, k - 1)) / k

我递归地写了它,因为它非常简单和漂亮,但如果你愿意的话,你可以把它变成一个迭代的解决方案。

答案 1 :(得分:28)

答案 2 :(得分:6)

计算二项式系数(n choose k)而不溢出的最简单方法可能是使用Pascal的三角形。不需要分数或乘法。 (n choose k)。 Pascal三角形的nth行和kth条目给出了值。

Take a look at this page。这是O(n^2)操作,只需添加,您可以使用动态编程解决。对于任何可以容纳64位整数的数字,它都会快速闪电。

答案 3 :(得分:4)

如果您要计算这样的许多组合,计算Pascal的三角形肯定是最好的选择。正如您已经知道递归公式,我想我可以在这里通过一些代码:

MAX_N = 100
MAX_K = 100

C = [[1] + [0]*MAX_K for i in range(MAX_N+1)]

for i in range(1, MAX_N+1):
    for j in range(1, MAX_K+1):
        C[i][j] = C[i-1][j-1] + C[i-1][j];

print C[10][2]
print C[10][8]
print C[10][3]

答案 4 :(得分:1)

n!/k!(n-k)!方法的问题与!增长非常快的问题的成本差别不大,因此,即使nCk的值都在nCk == product(i=1..k) (n-(k-i))/i的范围内,比方说,64位整数,中间计算不是。如果你不喜欢kainaw的递归加法方法,你可以尝试乘法方法:

product(i=1..k)

其中i表示1,2,...,k获取值{{1}}时所有字词的乘积。

答案 5 :(得分:1)

最快的方法可能是使用公式,而不是帕斯卡三角形。当我们知道我们稍后要用相同的数字除以时,让我们开始不做乘法。 如果k < n / 2,让我们有k = n - k。我们知道C(n,k)= C(n,n-k) 现在:

n! / (k! x (n-k)!) = (product of numbers between (k+1) and n) / (n-k)!

至少使用这种技术,你永远不会除以之前用过的数字。你有(n-k)个乘法和(n-k)个除法。

我正在考虑一种避免所有分歧的方法,通过在我们必须乘以的数字和我们必须分开的数字之间找到GCD。我稍后会尝试编辑。

答案 6 :(得分:0)

如果你有一个阶乘的查找表,那么C(n,k)的计算速度会非常快。

答案 7 :(得分:-3)

“效率最高”是一个糟糕的要求。你想要提高效率是什么?堆栈?记忆?速度?总的来说,我的观点是递归方法是最有效的,因为它只使用加法(廉价操作),并且递归对于大多数情况来说不会太糟糕。功能是:

nchoosek(n, k)
{
    if(k==0) return 1;
    if(n==0) return 0;
    return nchoosek(n-1, k-1)+nchoosek(n-1,k);
}