arr.append(curr) 和 arr.append(curr[:]) 之间的区别

Difference between arr.append(curr) and arr.append(curr[:])

生成幂集的函数给出了正确的输入。 但是,在将 append(curr[:]) 替换为 append(curr) 后,会给出一个空列表列表。 这是什么原因?

def subsets(nums):
    def backtrack(first = 0, curr = []):
        # if the combination is done
        if len(curr) == k:  
            output.append(curr)
            return
        for i in range(first, n):
            # add nums[i] into the current combination
            curr.append(nums[i])
            # use next integers to complete the combination
            backtrack(i + 1, curr)
            # backtrack
            curr.pop()
    
    output = []
    n = len(nums)
    for k in range(n + 1):
        backtrack()
    return output

Using arr.append(curr[:]) 意味着追加 currCOPYarr.append(curr)curr 本身追加到数组 arr,意思是当你对 curr 做任何改变时,它在 arr 中的值也会相应地改变

您可以在此处阅读有关数组复制的更多信息:Link

arr.append(curr)arr.append(curr[:])的区别在于,第一个复制curr列表地址到arr,第二个复制[=16]的值=] 到 arr.

让我们通过例子看看区别。

第一种情况:

curr = [5, 10, 15, 20]
arr = []
arr.append(curr)
print("Before update")
print("Curr: {}\nArr: {}".format(curr, arr))
curr[1] = 7
print("After update")
print("Curr: {}\nArr: {}".format(curr, arr))

输出:

Before update
Curr: [5, 10, 15, 20]
Arr: [[5, 10, 15, 20]]
After update
Curr: [5, 7, 15, 20]
Arr: [[5, 7, 15, 20]]

第二种情况:

curr = [5, 10, 15, 20]
arr = []
print("Before update")
arr.append(curr[:])
print("Curr: {}\nArr: {}".format(curr, arr))
curr[1] = 7
print("After update")
print("Curr: {}\nArr: {}".format(curr, arr))

输出:

Before update
Curr: [5, 10, 15, 20]
Arr: [[5, 10, 15, 20]]
After update
Curr: [5, 7, 15, 20]
Arr: [[5, 10, 15, 20]]

正如您在第一个场景中看到的那样,currarr 都会在更改 curr 列表的一个索引值时更新。因为将 curr 附加到 arr 拥有相同的内存地址。

在第二种情况下,仅 curr 在更改 curr 列表的一个索引值时更新。因为将 [:] 附加到 arr 会将内容复制到 curr 列表到 arr 列表。

根据上述(理论),当您 运行 代码将 curr 更改为 curr[:] 时,您得到 [[], [], [], [], [], [], [], []] 的原因是因为在最后backtrack 函数中的行 curr.pop() 您正在一个接一个地删除最后一个元素,因此您要从位于相同 space 的列表中删除元素一直记忆,而不是从它的副本列表值。

正如其他答案所指出的,cur[:] 复制了 cur。如果不制作副本,output 最终会包含同一列表的许多副本 - 每次调用 cur.appendcur.pop.

时,每个列表都会被修改

列表最终为 ,因为每次调用 cur.append 都会调用 cur.pop,这确保了“最终”迭代cur 将是空的。