简体   繁体   English

python 中对这个递归问题的解释

[英]explanation to this recursion problem in python

check this sample code for backtracking, there are two ways I can append the variable i to curr before backtracking, the one here (not commented) updates the global ans array, whereas the other way doesn't (shown below).:检查此示例代码以进行回溯,有两种方法可以 append 变量i在回溯之前进行curr ,此处(未注释)更新全局ans数组,而另一种方法则不(如下所示):

n = 4
k = 2
ans = []
def backtrack(first, curr):
    if len(curr)==k:
        ans.append(curr)
    for i in range(first, n+1):
        # curr.append(i)
        backtrack(i+1, curr+[i])
        # curr.pop()

curr = []
backtrack(1, curr)
print("result = ",ans)

output here: result = [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]此处为 output: result = [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]

for the other way:另一种方式:

n = 4
k = 2
ans = []
def backtrack(first, curr):
    if len(curr)==k:
        ans.append(curr)
    for i in range(first, n+1):
        curr.append(i)
        backtrack(i+1, curr)
        curr.pop()

curr = []
backtrack(1, curr)
print("result = ",ans)

output here: result = [[], [], [], [], [], []]此处为 output: result = [[], [], [], [], [], []]

I wish to understand, what exactly changes here and why the global output array ans behaves differently我想了解,这里到底发生了什么变化以及为什么全局 output 数组ans的行为不同

curr+[i] creates a new object which gets passed to the next recursive call. curr+[i]创建一个新的 object ,它被传递给下一个递归调用。 So whenever you then append curr to ans with this version, you append a new object showing you a snapshot of what curr is which won't later get modified.因此,每当您使用此版本 append curr回答ans时,您 append 一个新的 object 向您显示curr是什么的快照,以后不会被修改。

When you instead use .append and .pop , you keep passing and having only one single object, so when you append it to ans it is really that unique object that you append everytime again and again.当您改为使用.append.pop时,您会一直传递并且只有一个 object,因此当您将 append 回答为ans时,它确实是您 append 每次一次又一次的唯一 object。 Then you will keep updating that unique object which will reflect on all element of ans since they are the same object. Given at the end of processing curr gets cleared you end up having only empty lists everywhere, even if at every step curr had actually the value you wanted.然后,您将继续更新唯一的 object,它将反映ans的所有元素,因为它们是相同的 object。鉴于在处理结束时curr被清除,您最终到处都只有空列表,即使在每一步curr实际上都有你想要的价值。

You can see that by adding this print first to check that apart from this bug, everything still works the same in both cases as you would expect:你可以看到,通过首先添加这个打印来检查除了这个错误之外,在这两种情况下,一切仍然像你期望的那样工作:

def backtrack(first, curr):
    print(first, id(curr), curr)
    # ... and the rest

To fix the second version, you can pass a copy instead:要修复第二个版本,您可以传递一个副本:

curr.append(i)
backtrack(i+1, curr.copy())
curr.pop()

or copy when you append to ans或在您将 append 复制到ans时复制

ans.append(curr.copy())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM