生成一组整数的不同大小的所有排列的算法?

时间:2016-12-15 23:15:07

标签: algorithm permutation

假设我有一个整数数组,例如[3,4,2,7,8,5]

如何从该阵列生成不同大小的排列?

喜欢获得所有可能的2对,或所有可能的3对? 4?

我希望能够很快完成这项工作。

2 个答案:

答案 0 :(得分:1)

对于与第一原则不同的语言方法:枚举大小为k的所有子集(对于k = 2,...,n,其中n是数组的大小)。关于组合的维基百科文章有关于enumeration的部分。对于每个枚举子集,使用Johnson-Trotter algorithm来枚举它的排列。这种排列的总数非常快。例如,只有10个项目有9,864,090

许多语言都有图书馆支持。例如,它是Python中的一个简单的编程练习(使用其itertools模块)。这是一个用于产生这种排列的发生器:

import itertools

def allPermutations(items):
    n = len(items)
    for k in range(2,n+1):
        for combo in itertools.combinations(items,k):
            for perm in itertools.permutations(combo):
                yield perm

例如,list(allPermutations([3,4,2,7,8,5]))评估从[3,4,2,7,8,5]中抽取的所有1950个此类排列的列表。

答案 1 :(得分:1)

您可以使用任何算法(例如众所周知的Narayana algorithm)来生成大小为N的所有排列。

现在,如果在这个排列的总序列中,你只考虑带前缀的排列(a 1 2 ,...,a k )其中a 1 < a 2 < ......< a k ,那么所有这些排列的尾部将形成一系列长度为N - k的所有可能排列。

通过对所有长度为N的排列进行单次传递,您可以生成长度为N且更短的所有排列。

这里是C ++实现的样子

#include <iostream>
#include <algorithm>
#include <iterator>

int main() 
{
  int a[] = { 2, 3, 4, 5, 7, 8 };

  do
  {
    for (auto ite = std::begin(a); ite != std::end(a); ++ite)
      if (std::is_sorted(std::begin(a), ite))
      {
        std::copy(ite, std::end(a), std::ostream_iterator<int>(std::cout));
        std::cout << std::endl;
      }

  } while (std::next_permutation(std::begin(a), std::end(a)));
}

(我冒昧地对你的输入集进行预先排序。)

以上显然不是最佳的,因为std::is_sorted周期内for的连续调用将重复重新扫描/重新检查前一次迭代中已经检查过的内容。但同样,此实现仅用于说明目的。

现在的问题是,您是否对生成这些排列的顺序感到满意。上述方法不会按长度分组。

或者,您可以遍历all possible combinations,然后为每个组合生成所有可能的排列。