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[:])
意味着追加 curr
的 COPY 而 arr.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]]
正如您在第一个场景中看到的那样,curr
和 arr
都会在更改 curr
列表的一个索引值时更新。因为将 curr
附加到 arr
拥有相同的内存地址。
在第二种情况下,仅 curr
在更改 curr
列表的一个索引值时更新。因为将 [:]
附加到 arr
会将内容复制到 curr
列表到 arr
列表。
根据上述(理论),当您 运行 代码将 curr
更改为 curr[:]
时,您得到 [[], [], [], [], [], [], [], []]
的原因是因为在最后backtrack 函数中的行 curr.pop()
您正在一个接一个地删除最后一个元素,因此您要从位于相同 space 的列表中删除元素一直记忆,而不是从它的副本列表值。
正如其他答案所指出的,cur[:]
复制了 cur
。如果不制作副本,output
最终会包含同一列表的许多副本 - 每次调用 cur.append
或 cur.pop
.
时,每个列表都会被修改
列表最终为 空,因为每次调用 cur.append
都会调用 cur.pop
,这确保了“最终”迭代cur
将是空的。
生成幂集的函数给出了正确的输入。 但是,在将 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[:])
意味着追加 curr
的 COPY 而 arr.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]]
正如您在第一个场景中看到的那样,curr
和 arr
都会在更改 curr
列表的一个索引值时更新。因为将 curr
附加到 arr
拥有相同的内存地址。
在第二种情况下,仅 curr
在更改 curr
列表的一个索引值时更新。因为将 [:]
附加到 arr
会将内容复制到 curr
列表到 arr
列表。
根据上述(理论),当您 运行 代码将 curr
更改为 curr[:]
时,您得到 [[], [], [], [], [], [], [], []]
的原因是因为在最后backtrack 函数中的行 curr.pop()
您正在一个接一个地删除最后一个元素,因此您要从位于相同 space 的列表中删除元素一直记忆,而不是从它的副本列表值。
正如其他答案所指出的,cur[:]
复制了 cur
。如果不制作副本,output
最终会包含同一列表的许多副本 - 每次调用 cur.append
或 cur.pop
.
列表最终为 空,因为每次调用 cur.append
都会调用 cur.pop
,这确保了“最终”迭代cur
将是空的。