这与leetcode问题39有关。
我从results.append(solution)
开始,它没有正确地添加到列表中,并在解决方案中发现results.append(solution[:])
可以正常工作。这两种语法有什么区别?
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
results=[]
def backtracking(candidates,target,start,solution,results):
#print(start,target,solution,results)
if target<0:
return
if target==0:
results.append(solution[:])
return
for i in range(start,len(candidates)):
solution.append(candidates[i])
backtracking(candidates,target-candidates[i],i,solution,results)
solution.pop()
backtracking(candidates,target,0,[],results)
return results
答案 0 :(得分:3)
a[:]
将创建一个新列表。
c.append(b)
将列表b
附加到c
。
以下代码将有助于更好地理解这一点-
>>> a=[1,2,3]
>>> b=[4,5]
>>> c=[1,2,3]
>>> a.append(b) #append b
>>> c.append(b[:]) #create new list and append
>>> a
[1, 2, 3, [4, 5]]
>>> c
[1, 2, 3, [4, 5]]
>>> b
[4, 5]
>>> a[3][0]=99 #modify a
>>> a
[1, 2, 3, [99, 5]] #a modified
>>> b
[99, 5] #so does b
>>> c
[1, 2, 3, [4, 5]] #modify c
>>> c[3][1]=99
>>> c #c modified
[1, 2, 3, [4, 99]]
>>> b #original b did not get modified
[99, 5]
>>>
答案 1 :(得分:1)
从对象id
中可以看到,进行切片会创建一个新列表
>>> a = [1, 2, 3]
>>> id(a)
2711680383816
>>> id(a[:])
2711683338696
直接分配列表是指同一对象
>>> b = a
>>> id(b)
2711680383816
答案 2 :(得分:0)
a
是一个列表,a[:]
是一个复制了所有元素的新列表。
>>> a = [1, 2, 3]
>>> a == a[:]
True
>>> a is a[:]
False
我们还有另一个列表b = ["a", "b"]
。 append
将您提供的所有内容添加到列表的末尾。如果您追加另一个列表,则对该列表的 reference 会被添加,并可能导致意外的行为:
>>> b.append(a)
>>> b
["a", "b", [1, 2, 3]]
>>> a[0] = "c"
>>> b
["a", "b", ["c", 2, 3]]
>>> b[2][1] = 42
>>> a
["c", 42, 3]
>>> a is b[2]
True
您可以看到,在追加a
之后,如果您在a
中更改了元素,那么它在b
中也会更改。这是因为b
仅对a
具有引用。为防止这种情况,您可以改为执行b.append(a[:])
。这将复制 a
中的值,因此当您随后更改a
中的值时,b
中的值将保持复制时的状态:>
>>> b.append(a)
>>> b
["a", "b", [1, 2, 3]]
>>> a[0] = "c"
>>> b
["a", "b", [1, 2, 3]]
>>> b[2][1] = 42
>>> a
["c", 2, 3]
>>> a is b[2]
False
因此,在您的问题中,使用solution[:]
确保results
的下一次迭代发生solution.append
时添加到for
的内容不会改变循环。