【问题标题】:Listing all permutations of a given set of values列出给定值集的所有排列
【发布时间】:2012-03-26 19:57:28
【问题描述】:

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

【问题讨论】:

标签: algorithm permutation


【解决方案1】:

您可以在性能、特定分布和简单性之间进行选择。我所说的特定分布是指您是否关心输出的某些特定顺序,例如字典顺序。

据我所知,性能最好的算法是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)) 性能估计如下。

(此算法也适用于转换为性能良好的随机排列生成器。)

【讨论】:

  • 什么是字典式算法?任何其他用于比较的oes。顺便说一句,感谢您的评论。
【解决方案2】:

这个问题已经被问及回答了(事实上很多次):

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);
    }
}

【讨论】:

  • 我认为这是不正确的。您在递归步骤中尝试做的是:给定集合 S,生成 S-{a} 的所有排列,然后将 a 添加到每个排列中。这是错误的,因为您应该将该元素输入到每个排列的每个元素的 EVER 位置
  • @Bober02 :我不关注你。 “我应该把那个元素输入到每一个排列的每一个地方?”例如:{1,1,1,1,1} ..?这不是一个排列。
猜你喜欢
  • 1970-01-01
  • 2014-06-28
  • 2021-09-19
  • 1970-01-01
  • 1970-01-01
  • 2018-10-07
  • 2011-05-13
  • 1970-01-01
相关资源
最近更新 更多