我有V
非负整数的列表或向量n
。有一些正整数相等且相邻,比如V=[2, 3, 3, 0, 0]
。 (我不关心零整数。)
我想找到V
的所有唯一排列,以便所有相同且正整数保持相邻。如何为此编写算法? (对于实现,您可以选择Python或Matlab或任何其他语言。)
在Matlab和V=[2, 3, 3, 0, 0]
的例子中,我得到了所有独特的permations如下:
V = [2, 3, 3, 0, 0];
unique(perms([2, 3, 3, 0, 0]), 'rows')
我得到了:
0 0 2 3 3
0 0 3 2 3
0 0 3 3 2
0 2 0 3 3
0 2 3 0 3
0 2 3 3 0
0 3 0 2 3
0 3 0 3 2
0 3 2 0 3
0 3 2 3 0
0 3 3 0 2
0 3 3 2 0
2 0 0 3 3
2 0 3 0 3
2 0 3 3 0
2 3 0 0 3
2 3 0 3 0
2 3 3 0 0
3 0 0 2 3
3 0 0 3 2
3 0 2 0 3
3 0 2 3 0
3 0 3 0 2
3 0 3 2 0
3 2 0 0 3
3 2 0 3 0
3 2 3 0 0
3 3 0 0 2
3 3 0 2 0
3 3 2 0 0
如你所知,我得到30
这样的排列。在这些30
中,有18
不尊重邻接约束。例如,[3, 2, 3, 0, 0]
不能出现在最终结果中,因为3
不再与3
相邻。最后,所有独特的排列都可以通过以下方式给出:
0 0 2 3 3
0 0 3 3 2
0 2 0 3 3
0 2 3 3 0
0 3 3 0 2
0 3 3 2 0
2 0 0 3 3
2 0 3 3 0
2 3 3 0 0
3 3 0 0 2
3 3 0 2 0
3 3 2 0 0
我想到的第一个想法(也是最简单的想法)是生成所有独特的排列,然后为每个排列验证约束。但是还有其他有效的算法吗?
答案 0 :(得分:1)
一个简单的算法是:
1.遍历初始表并创建另一个包含两行的表:
input: V = [2, 3, 3, 0, 0];
new array: V2 = |2,3,0|
|1,2,2|
正如你所看到的,V2来自V,保留一次元素,第二行计算我们看到它们的次数。
对于每一个结果,例如:
V2 = |3,2,0|
|2,1,2|
你已经保留了元素出现的次数。
答案 1 :(得分:1)
我们可以先压缩给定的数组,这样每个正数只有一个条目,同时保持每个数字出现次数的计数(零应保留原样)。
生成压缩数组的排列。
解压缩每个排列并仅保留唯一排列。
def compress(arr):
counts = {}
compressed = []
curr_ele = arr[0]
count_ele = 0
for ele in arr:
if ele != curr_ele or ele == 0:
counts[curr_ele] = count_ele
compressed.append(curr_ele)
count_ele = 1
curr_ele = ele
else:
count_ele += 1
counts[curr_ele] = count_ele
compressed.append(curr_ele)
return compressed, counts
def uncompress(arr, counts):
res = []
for ele in arr:
if ele == 0:
res.append(0)
continue
num_reps = counts[ele]
for _ in range(num_reps):
res.append(ele)
return res
import itertools
ip = [2, 3, 3, 0, 0]
ip_compressed, counts = compress(ip)
set([tuple(uncompress(perm, counts)) for perm in itertools.permutations(ip_compressed)])
{(0, 0, 2, 3, 3),
(0, 0, 3, 3, 2),
(0, 2, 0, 3, 3),
(0, 2, 3, 3, 0),
(0, 3, 3, 0, 2),
(0, 3, 3, 2, 0),
(2, 0, 0, 3, 3),
(2, 0, 3, 3, 0),
(2, 3, 3, 0, 0),
(3, 3, 0, 0, 2),
(3, 3, 0, 2, 0),
(3, 3, 2, 0, 0)}