我今天正在研究某人使用Python3的堆算法回溯的解决方案。解决方案如下:
def permute(self, nums):
def backtrack(start, end):
if start == end:
ans.append(nums[:])
for i in range(start, end):
nums[start], nums[i] = nums[i], nums[start]
backtrack(start+1, end)
nums[start], nums[i] = nums[i], nums[start]
ans = []
backtrack(0, len(nums))
return ans
现在我正在看ans.append(nums[:])
行,写nums[:]
的意义是什么?无法正确编写nums
函数吗?
答案 0 :(得分:7)
请考虑以下内容
>>> a = [1,2,3]
>>> b = [a]
>>> b[0].append(4)
>>> a
[1, 2, 3, 4]
如您所见,修改b[0]
会修改a
,因为您已将对象a
存储在b
中,而不仅仅是a
的值。因此,使用[:]
可以复制列表。
>>> a = [1,2,3]
>>> b = [a[:]]
>>> b[0].append(4)
>>> a
[1, 2, 3]
所以重点是传递值,而不是对象本身。
答案 1 :(得分:2)
不,这是不一样的,因为在for循环中您正在突变nums
nums[start], nums[i] = nums[i], nums[start]
如果在答案中附加对nums
的引用,而不是独立复制,则将对所有组装者的子元素进行突变,并最终列出所有反映最终值的相同置换。您可以尝试一下并查看结果:
def permute(nums):
def backtrack(start, end):
if start == end:
ans.append(nums)
for i in range(start, end):
# changing sums which will be reflected in all
# references to nums in the ans array
nums[start], nums[i] = nums[i], nums[start]
backtrack(start+1, end)
nums[start], nums[i] = nums[i], nums[start]
ans = []
backtrack(0, len(nums))
return ans
permute([1, 2, 3])
都一样:
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
您可以确认它们都指向内存中的同一对象:
l = permute([1, 2, 3])
[id(el) for el in l]
> [140539119291912, # all the same reference
140539119291912,
140539119291912,
140539119291912,
140539119291912,
140539119291912]
通过使用ans.append(nums[:])
,您可以进行复制,因此nums
的进一步突变不会影响您已经拥有的组合。