解释了Python中此递归问题的说明

发布于 2025-02-03 20:37:55 字数 848 浏览 2 评论 0原文

检查此示例代码是否进行回溯,有两种方法可以将变量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)

],[2,4],[3,4]]

另一种方式:

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)

在此处输出:result = [[],[],[],[],[],[],[],[],[]]

我想理解,这里到底发生了什么变化以及为什么全局输出阵列ans行为不同

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).:

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]]

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 = [[], [], [], [], [], []]

I wish to understand, what exactly changes here and why the global output array ans behaves differently

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

情丝乱 2025-02-10 20:37:55

Curr+[I]创建一个新对象,该对象将传递给下一个递归调用。因此,每当您将Curr>附加到ANS的情况稍后修改。

当您使用.append.pop时,您一直通过一个对象,因此,当您将其附加到ANS时,它是实际上,您一次又一次地附加的那个独特的对象。然后,您将继续更新该唯一对象,该对象将反映ans的所有元素,因为它们是同一对象。处理Curr在清除处理时给出您最终只有空的列表,即使在每个步骤Curr实际上都具有您想要的值。

您可以看到,首先添加此打印件以检查除此错误外,在这两种情况下,一切仍然与您期望的情况相同:

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

要修复第二版,您可以通过副本传递:

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

或当您附加到<<时复制代码> ans

ans.append(curr.copy())

curr+[i] creates a new object which gets passed to the next recursive call. 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.

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. 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.

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

ans.append(curr.copy())
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文