我感兴趣的是可以用来生成给定集合的所有潜在排列的不同技术/方法的比较。
答案 0 :(得分:6)
您可以选择性能,特定分布和简单性。通过特定的分布,我的意思是,你是否关心输出的某些特定顺序,例如词典。
据我所知,表现最佳的算法是Steinhaus algorithm。在某种意义上,乘法常数是最优的,只需要一定数量的处理器指令来生成一个排列(不计算打印输出所需的指令,并不总是需要)。
还有一个非常简单的算法可以按字典顺序生成排列,您可能会自己重新创建一个递归过程,其性能为 O(n.log(n).log( n)),因此与通过任何其他方法生成列表并对其进行排序大致相同。
编辑:这是简单算法的伪代码:
void permute(Element[] permutationPrefix, Set rest)
{
if (rest.IsEmpty) {
// permutationPrefix is now a full permutation
print(permutationPrefix);
} else {
foreach (element in rest) {
permutationPrefix.Append(element);
permute(permutationPrefix, rest.Minus(element))
permutationPrefix.Length--; // cut away the last item
}
}
}
最初使用空permutationPrefix
和rest
调用此设置;如果此集合是排序数据结构,则排列将以字典顺序输出。
请注意,我们在每次递归调用时复制和修改集合,这是整个算法中最昂贵的操作,可能与print
方法一起使用。单个集合副本的成本在排列总数n
中是对数的;并且因为递归调用堆栈的深度也是对数的,所以 O(n.log(n).log(n))性能估计如下。
(此算法也适合转换为性能良好的随机置换生成器。)
答案 1 :(得分:-1)
这个问题已经被提出并得到了回答(实际上很多次):
Algorithm to generate all possible permutations of a list?
Permutations with a given integer
就我个人而言,我认为Steinhaus算法过度思考问题:它并不比最天真的实现快得多。
最天真实现的类似Java的伪代码:
List<List<Element>> generateAllPermutations(List<Element> input)
{
List<Element> output = new ArrayList<Element>();
if (input.size() == 0)
return output;
for (Element first : input) {
for (List<Element> sequence : generateAllPermutations(input - first))
output.add(first + sequence);
}
}