当我想写一个简单的排列代码时,我遇到了一个问题,
def permutation(Ori, Curr, used):
if len(Ori) == len(Curr):
#print Curr
return
for i in xrange(len(Ori)):
if used[i]:
continue
used[i] = True
Curr.append(Ori[i])
print Curr,i," after append"
permutation(Ori, Curr, used) # further level
used[i] = False
print Curr,i," before delete"
Curr = Curr[0:-1] # Curr.pop() works
print Curr,i," after delete"
return
if __name__ == "__main__":
used = [False]*3
Curr = []
permutation([1,2,3], Curr, used)
虽然结果不正确:
[1] 0 after append
[1, 2] 1 after append
[1, 2, 3] 2 after append
[1, 2, 3] 2 before delete
[1, 2] 2 after delete <------
[1, 2, 3] 1 before delete <------
[1, 2] 1 after delete
[1, 2, 3] 2 after append
[1, 2, 3] 2 before delete
[1, 2] 2 after delete
[1, 2, 3] 0 before delete
[1, 2] 0 after delete
[1, 2, 2] 1 after append
[1, 2, 2] 1 before delete
[1, 2] 1 after delete
[1, 2, 3] 2 after append
[1, 2, 3] 2 before delete
[1, 2] 2 after delete
我不知道为什么数组在我指出的步骤中有额外的数字。
对不起,也许我还没有明白我的问题,我只是想知道递归返回列表的原因,我认为它已被缩小。 我写了另一段代码,谁能告诉我两个注释句子之间的区别?(A = A [0:-1]和A.pop())
def f(A):
if(len(A) == 10):
return
A.append('a')
f(A)
print A
# A = A[0:-1]
# A.pop()
return
if __name__ == "__main__":
f([])
答案 0 :(得分:4)
在
行permutation(Ori, Curr, used) # further level
您正在传递指向列表的指针,而不是列表的副本。执行此操作时,permutation
修改Curr
时,您会在调用上下文中看到修改。一种可能的解决方案是致电
permutation(Ori, Curr[:], used) # further level
传递了Curr的副本。
因为它会修改Curr
。它确实在函数返回之前从Curr
中删除了元素。
使用Curr = Curr[0:-1]
创建一个Curr
的副本,但没有一个元素。该元素不会从原始列表中删除(调用上下文仍然可以访问该列表)。所以它几乎没有做任何事情,因为一旦函数返回,就会忘记没有最后一个元素的新列表。
另一种可能的解决方案是不要更改收到的Curr
- 替换
Curr.append(Ori[i])
带
Curr = Curr + [Ori[i]]
答案 1 :(得分:1)
已经有一个生成排列的功能:
http://docs.python.org/library/itertools.html#itertools.permutations
根据我的拙见,示例代码(根据product
定义)是“通常的”基于生成器的实现。
如果考虑有用,这里是生成迭代的所有排列的代码:
def permutations(iter):
"""
>>> print(list( permutations(range(3)) ))
[[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
"""
elements = list(iter)
# base case
if len(elements)==0:
yield []
for i,elem in enumerate(elements):
withoutElem = elements[:i]+elements[i+1:]
for perm in permutations(withoutElem):
yield [elem]+perm