我试图在寻找独特的permutions的问题中使用回溯。我写了这个:
def f(A, start, end):
if start == end - 1:
print(A)
else:
for idx in range(start, end):
if idx != start and A[idx] == A[start]:
continue
A[idx], A[start] = A[start], A[idx]
f(A, start + 1, end)
此示例有效
A = [2, 3, 2]
f(A, 0, len(A))
[2, 3, 2]
[2, 2, 3]
[3, 2, 2]
这个没有用
A = [2, 2, 1, 1]
f(A, 0, len(A))
[2, 2, 1, 1]
[2, 1, 2, 1]
[2, 1, 1, 2]
[2, 2, 1, 1] #unwanted duplicate!
[1, 2, 2, 1]
[1, 2, 1, 2]
[1, 1, 2, 2]
[1, 2, 2, 1]
[1, 2, 1, 2]
[2, 2, 1, 1]
[2, 1, 2, 1]
[2, 1, 1, 2]
[2, 2, 1, 1]
为什么结果中仍然有重复项?
答案 0 :(得分:0)
你的输入数组中有重复的元素。这可能会导致解决方案中的元素冗余或冗余排列,但如果您使用了数组中的唯一元素等输入,例如......
A = [1,2,3,4 ...]等等以下代码可能会有所帮助
def f(A, start, end):
if start == end - 1:
print(A)
else:
for idx in range(start, end):
if idx != start and A[idx] == A[start]:
continue
A[idx], A[start] = A[start], A[idx]
f(A, start + 1, end)
A[idx], A[start] = A[start], A[idx] #This is added
这个例子......
A = [1, 2, 3, 4]
f(A, 0, len(A))
OUTPUT是......
[1, 2, 3, 4]
[1, 2, 4, 3]
[1, 3, 2, 4]
[1, 3, 4, 2]
[1, 4, 3, 2]
[1, 4, 2, 3]
[2, 1, 3, 4]
[2, 1, 4, 3]
[2, 3, 1, 4]
[2, 3, 4, 1]
[2, 4, 3, 1]
[2, 4, 1, 3]
[3, 2, 1, 4]
[3, 2, 4, 1]
[3, 1, 2, 4]
[3, 1, 4, 2]
[3, 4, 1, 2]
[3, 4, 2, 1]
[4, 2, 3, 1]
[4, 2, 1, 3]
[4, 3, 2, 1]
[4, 3, 1, 2]
[4, 1, 3, 2]
[4, 1, 2, 3]
希望这可以帮助你:)
答案 1 :(得分:0)
这是因为您正在将切换应用到您的列表中。 (即:您在计算排列时修改列表A。)
这是代码的快速修补程序:
def f(A, start, end):
if start == end - 1:
print(A)
else:
B = A.copy()
for idx in range(start, end):
if idx != start and B[idx] == B[start]:
continue
B[idx], B[start] = A[start], A[idx]
f(B, start + 1, end)
A = [2, 2, 1, 1]
f(A, 0, len(A))
# [2, 2, 1, 1]
# [2, 1, 2, 1]
# [2, 1, 1, 2]
# [1, 2, 2, 1]
# [1, 2, 1, 2]
# [1, 1, 2, 2]
答案 2 :(得分:0)
如果您想避免重复数字造成的重复,您可以先对数据进行排序,然后添加条件进行交换(仅当元素较大时):
def f_s(A, start, end):
f(sorted(A), start, end)
def f(A, start, end):
if start == end - 1:
print(A)
else:
for idx in range(start, end):
if idx != start and A[idx] == A[start]:
continue
if A[idx] >= A[start]:
A[idx], A[start] = A[start], A[idx]
f(A, start + 1, end)
A = [2, 3, 2]
f_s(A, 0, len(A))
A = [2, 2, 1, 1]
f_s(A, 0, len(A))
输出:
[2, 2, 3]
[2, 3, 2]
[3, 2, 2]
[1, 1, 2, 2]
[1, 2, 1, 2]
[1, 2, 2, 1]
[2, 1, 2, 1]
[2, 2, 1, 1]
答案 3 :(得分:0)
在过滤中,您使用一对一检查。因此,不从超过三个元素的那一刻开始工作。
这是因为,您可以在多次(真实)掉期后获得相同的排列。例如:
[1 ,2(1),2(2),3 ] -> swap 1 with 3
[1 ,3, 2(2),2(1)] -> swap 1 with 2
[1 ,2(2),3 ,2(1)] -> swap 2 with 3
[1 ,2(2),2(1),3 ]
正如你所看到的那样,排列是相同的(但两个两个的起源是不同的)。所以我们间接地交换了两个两个。
尽管如此,没有必要让它变得那么复杂。有两种方法可以在这里起作用:
Counter
,然后确保根据计数器发出)。后者运行得更快,因为它不会产生必须省略的排列。
示例实现可以是:
from collections import Counter
def f(lst):
def g(l,c,n):
if n <= 0:
yield tuple(l)
else:
for k,v in c.items():
if v > 0:
c[k] -= 1
l.append(k)
for cfg in g(l,c,n-1):
yield cfg
l.pop()
c[k] += 1
for cfg in g([],Counter(lst),len(lst)):
yield cfg
这给出了:
>>> list(f([1,1,2,2]))
[(1, 1, 2, 2), (1, 2, 1, 2), (1, 2, 2, 1), (2, 1, 1, 2), (2, 1, 2, 1), (2, 2, 1, 1)]
>>> list(f([1,1,2,2,3]))
[(1, 1, 2, 2, 3), (1, 1, 2, 3, 2), (1, 1, 3, 2, 2), (1, 2, 1, 2, 3), (1, 2, 1, 3, 2), (1, 2, 2, 1, 3), (1, 2, 2, 3, 1), (1, 2, 3, 1, 2), (1, 2, 3, 2, 1), (1, 3, 1, 2, 2), (1, 3, 2, 1, 2), (1, 3, 2, 2, 1), (2, 1, 1, 2, 3), (2, 1, 1, 3, 2), (2, 1, 2, 1, 3), (2, 1, 2, 3, 1), (2, 1, 3, 1, 2), (2, 1, 3, 2, 1), (2, 2, 1, 1, 3), (2, 2, 1, 3, 1), (2, 2, 3, 1, 1), (2, 3, 1, 1, 2), (2, 3, 1, 2, 1), (2, 3, 2, 1, 1), (3, 1, 1, 2, 2), (3, 1, 2, 1, 2), (3, 1, 2, 2, 1), (3, 2, 1, 1, 2), (3, 2, 1, 2, 1), (3, 2, 2, 1, 1)]
答案 4 :(得分:0)
威廉姆(Willem)的answer略有变化,它利用了yield from并解释了发生的事情。我们避免枚举重复元素,但仍对数据进行排序以按字典顺序发出排列。
data class Geo(
@SerializedName("lat")
var lat: String,
@SerializedName("lng")
var lng: String
)
输出:
def multiset_permutation(A):
def solve_permutation(depth, counter, permutation):
# base case/goal
if depth == 0:
yield permutation
return
# choices
for key, value in counter.items():
# constraint
if value > 0:
# make a choice
counter[key] -= 1
permutation.append(key)
# explore
yield from [
list(i) for i in solve_permutation(depth - 1, counter, permutation)
]
# backtrack - undo our choices
permutation.pop()
counter[key] += 1
"""
Lexicographical order requires that we sort the list first so that we
incrementally emit the next larger permutation based on the counters
"""
A = sorted(A)
counter = collections.Counter(A)
return list(solve_permutation(len(A), counter, []))
调用堆栈来解决[[1, 1, 2], [1, 2, 1], [2, 1, 1]]
如下所示:
[1, 1, 2]
递归树:
depth counter permutation
0, {1:0, 2:0}, [1,1,2]
1, {1:0, 2:1}, [1,1]
2, {1:1, 2:1}, [1]
3, {1:2, 2:1}, []
0, {1:0, 2:0}, [1,2,1]
1, {1:0, 2:1}, [1,2]
2, {1:1, 2:1}, [1]
0, {1:0, 2:0}, [2,1,1]
1, {1:0, 2:1}, [2,1]
2, {1:1, 2:1}, [2]
3, {1:2, 2:1}, []