列出给定值集的所有排列

时间:2012-03-26 19:57:29

标签: algorithm permutation

我感兴趣的是可以用来生成给定集合的所有潜在排列的不同技术/方法的比较。

2 个答案:

答案 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
        }
    }
}

最初使用空permutationPrefixrest调用此设置;如果此集合是排序数据结构,则排列将以字典顺序输出。

请注意,我们在每次递归调用时复制和修改集合,这是整个算法中最昂贵的操作,可能与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);
    }
}