Python 你能解释一下这个“递归”吗;n选择“k”;对我说什么?
下面是一个带有参数n和k的子集问题的代码。n表示学生总数,k表示我希望从n中获得的学生数量。代码试图给出从n个学生中抽取k个学生的可能组合数Python 你能解释一下这个“递归”吗;n选择“k”;对我说什么?,python,recursion,Python,Recursion,下面是一个带有参数n和k的子集问题的代码。n表示学生总数,k表示我希望从n中获得的学生数量。代码试图给出从n个学生中抽取k个学生的可能组合数 def subset(n, k): if k == 0: return 1 if n == k: return 1 else: return subset(n-1, k-1) + subset(n-1, k) 我理解递归调用的第一部分,但理解+子集(n-1,k)部分有困难。有人能给
def subset(n, k):
if k == 0:
return 1
if n == k:
return 1
else:
return subset(n-1, k-1) + subset(n-1, k)
我理解递归调用的第一部分,但理解+子集(n-1,k)部分有困难。有人能给我解释一下吗?这更像是一个数学问题,而不是一个编程问题。你要做的是计算二项式系数,公式是
(n, k) = (n-1, k-1) + (n-1, k) with all (n, 0) and (n, n) having a value of 1.
请看完整的解释。可以看到递归解决方案。如果提到的链接无效,只需使用谷歌搜索即可。我怀疑你在维基百科上读过这篇文章后,会得到比这更好的解释。递归是基于一个简单的观察,对此我将给出一个组合论证,解释为什么它是真的,而不是通过公式进行数学证明 无论何时从
n
中选择k
元素,都有两种情况:
#n
#n
#n
时的组合量和未选择#n
时的组合量给出
选择元素#n
因为我们已经选择了一个元素,所以只需要选择另一个k-1
元素。此外,既然我们已经决定了一个元素——关于它是否被包含——我们只需要考虑剩下的<代码> N-1 元素。
因此,用于选择元素#n
的组合量如下所示:
subset(n - 1, k - 1)
不选择元素#n
仍然有k
元素可供选择,但由于我们已经对元素#n
下了决心,因此只剩下n-1
元素可供选择。因此:
subset(n - 1, k)
基本情况
递归使用了这样一个事实,即我们通常可以区分两种情况,元素n
是该解决方案一部分的解决方案,以及元素n不是该解决方案一部分的解决方案
然而,这种区分并不总是可以做到:
- 选择所有元素时(对应于下面代码中的大小写
n==k
)
- 或者完全不选择任何元素时(对应于下面代码中的大小写
k==0
)
在这些情况下,只有一种解决方案,因此
if k == 0:
return 1
if n == k:
return 1
确保它起作用
要做到这一点,我们需要说服自己(或证明)基本情况总是在某个时候发生
让我们假设,n
在某个点。由于根据我们的假设,n
最初大于或等于k
,因此肯定存在n=k
的某个点,因为n
和k
一致减少,或者只有n
减少了一个,即它如下所示
这意味着,必须调用子集(n-1,k)
,才能发生n
降低到k
以下。然而,这是不可能的,因为我们在n=k
上有一个基本情况,其中我们返回一个常量1
我们得出结论,要么n
在某一点上减少,使n=k
,要么一致减少k
次,使k=0
因此,基本情况有效。代码片段:
if k == 0:
return 1
if n == k:
return 1
使用两个组合事实:
nC0 = 1
nCn = 1
作为基本情况
接下来,执行以下递归调用:
return subset(n-1, k-1) + subset(n-1, k)
将以下事实直接转换为代码:
nCr = (n-1)C(k-1) + (n-1)Ck
如果您难以理解上述公式的适用性,请继续阅读:
在nCr中,我们从n中选择r项。如果我们考虑任何特定的项目:< /P>,选择可以分为两个相互排斥的类。
- 项目出现在r个所选项目中
在这种情况下,我们必须从剩余的n-1项中选择剩余的r-1项。这可以在(n-1)C(k-1)中完成
- 项目不会出现在r个所选项目中
在这种情况下,我们必须从剩余的n-1项中选择所有r项,这些项可以(n-1)Ck方式完成
我们把这两个加起来,因为我已经说过,这两个类是互斥的,因此它们共同构成了从n中选择r项的总方法。不过,我真的对递归感到困惑。