我正在实现一种算法,以查找n个元素中所有m个元素的所有组合。
我已经通过答案验证了整个代码,但是由于没有注释,所以有些部分很难理解,所以我写了一个问题。
例如,对于输入,n = 7,对于to_pick,n = 4,因此smallest = 0
是因为函数内的len(picked) == 0
。然后,如果将smallest(0)
插入了for语句的选取列表中,并且再次to_pick == 0
至pick(n, picked, to_pick-1)
中插入了选取,则返回选取。 ([0,1,2,3])
但是接下来,我无法理解拣选过程为[0,1,2,4]。当to_pick == 0
时,返回函数(返回的是if语句而不是函数吗?)我想知道何时执行picked.pop()
。
如果我有任何误解,请寻求指导。
代码
def pick(n, picked, to_pick):
if to_pick is 0:
return print(picked)
if len(picked) is 0:
smallest = 0
else:
smallest = picked[-1] + 1
for next in range(smallest, n):
picked.append(next)
pick(n, picked, to_pick - 1)
picked.pop()
if __name__ == '__main__':
result = list()
pick(7, result, 4)
答案 0 :(得分:0)
想象一下:
result = []
pick(7, result, 4)
此代码的作用是在第一次调用时会将您的最小数字设置为0。因此,此时您有smallest=0, n=7, to_pick=4
。从这一刻开始,您将拥有:
1-您的代码进入循环,您的空列表将附加最小值。
2-之后,该函数将被递归调用,这一次您的to_picked值减小了1。
3-您当前的最小值将是前一个最小值+ 1,然后再次转到第二行。
4-达到最终条件后,将打印列表。第一次是[0,1,2,3]。您将退出上一个递归函数,然后转到下一行。
5-这次将弹出最后一个项目。因此,您的列表将为[0,1,2]。
6-您在循环中更进一步,这次您的下一个值将是最小值+ 1,而您的最小值是3。这将被附加,因此您的列表将是[0,1,2, 4]。
编辑:所以我发现您的主要问题是,您不了解递归函数中return的工作方式。假设您有这样的非递归函数:
def foo(A):
return A
def bar(B):
result = foo(B)
return result
函数bar
完成工作后,在函数foo
中,它将返回到上一个作用域,即函数bar
的作用域,下一行将被执行。是return result
。
递归函数的逻辑相同,不同之处在于您一次又一次地调用同一函数。达到最终条件后,您将返回到先前的范围,直到再次达到最终条件为止。而且此操作将重复进行,直到您达到所有可能的最终条件。
因此,在您的情况下,第一次达到最终条件时将具有:
n=7, picked = [0,1,2], smallest = 2, n = 1
从最终条件返回后,选择的数组将为[0,1,2,3]
,代码将执行下一行。将会是picked.pop()
。因此,您将再次以picked = [0,1,2]
结尾,但是这次您已到达循环的最后一行。
因此,下一次您的next
值将由smallest + 1
或4
更新,这将再次重复直到循环结束。并且您将再次以[0,1,2]
结尾。
循环结束后,您的函数将返回上一个作用域。这次将弹出[0,1,2]
,您将得到[0,1]
,然后重复该过程。