我整理了一个函数,可以使用递归查找组合,而不会达到python中的内置限制。例如,您可以计算:选择(1000,500)。 这就是现在的样子:
def choose(n, k):
if not k:
return 1 .
elif n < k:
return 0
else:
return ((n + 1 - k) / k) * choose(n, k - 1)
它完全按照我希望的方式工作。如果k为0,则返回1,如果n小于k,则返回0(这是根据我在维基百科上找到的数学定义)。但是,问题是我不太了解最后一行(当我浏览网络时找到了它)。此刻我正在使用的最后一行之前,这是我在函数中拥有的最后一行:
return choose(n-1,k-1) + choose(n-1, k)
我也在Wikipedia上找到了(尽管我也不是100%理解)。但是由于python中的内置限制,它总是会导致错误,而我正在使用的新行不会导致这种错误。我知道新行在程序中的工作效率更高,因为例如,我们不将其拆分为两个子问题。
再说一遍..我要问的是,是否有任何一种灵魂可以(以一种可以理解的方式)解释这一行代码在函数中的工作方式:
return ((n + 1 - k) / k) * choose(n, k - 1)
答案 0 :(得分:0)
您首先需要知道如何定义组合C(n,k)。 C(n,k)的公式为:
或等效地:
可以重新构造为递归表达式:
这是您实现的。
对于第二种实现,这是Pascal's formula。递归实现将非常慢(并且可能会堆栈溢出,是的)。一种更有效的实现方式是将每个C(n,k)存储在二维数组中,以便按顺序计算每个值。
答案 1 :(得分:0)
剧透:最重要的是您应该使用封闭格式n! / (k! (n - k)!)
。
在许多其他语言中,解决方案是使函数tail-recursive,尽管Python不支持这种优化。因此,实施递归解决方案根本不是最佳选择。
您可以使用sys.setrecursionlimit
来增加最大递归深度,但这并不是最佳选择。
一种改进是通过迭代计算 n-choose-k 。
def choose(n, k):
if n < k:
return 0
ans = 1
while k > 0:
ans *= (n + 1 - k) / k
k -= 1
return ans
尽管如此,由于浮点运算,以上内容会累积一个错误。因此,最好的方法是使用 n-choose-k 的封闭形式。
from math import factorial
def choose(n, k):
return factorial(n) / (factorial(k) * factorial(n - k))