具有一些固定数字的排列

时间:2011-01-19 21:07:08

标签: c++ algorithm permutation

如果我需要在指定地点使用某个字符/数字,如何有效地生成数字的排列(或单词中的字符)?

e.g。从头开始在第二位生成数字3 的所有数字,在数字末尾的第二位生成数字1 。数字中的每个数字必须是唯一的,您只能选择数字 1-5

4 3 2 1 5
4 3 5 1 2
2 3 4 1 5
2 3 5 1 4
5 3 2 1 4
5 3 4 1 2

我知道有一个next_permutation函数,所以我可以准备一个数字为{4,2,5}的数组并将其循环发布到此函数,但是如何处理固定位置?

4 个答案:

答案 0 :(得分:6)

生成2 4 5的所有排列,并在输出例程中插入3和1。只要记住他们必须的立场:

int perm[3] = {2, 4, 5};
const int N = sizeof(perm) / sizeof(int);

std::map<int,int> fixed;  // note: zero-indexed
fixed[1] = 3;
fixed[3] = 1;

do {
    for (int i=0, j=0; i<5; i++)
        if (fixed.find(i) != fixed.end())
            std::cout << " " << fixed[i];
        else
            std::cout << " " << perm[j++];
    std::cout << std::endl;
} while (std::next_permutation(perm, perm + N));

输出

 2 3 4 1 5
 2 3 5 1 4
 4 3 2 1 5
 4 3 5 1 2
 5 3 2 1 4
 5 3 4 1 2

答案 1 :(得分:1)

我已经阅读了其他答案,我相信他们比你的具体问题更好。但是,我正在回答,以防有人需要一个通用的解决方案来解决你的问题。

我最近需要生成3个独立连续范围[first1,last1] + [first2,last2)+ [first3,last3]的所有排列。这与您的情况相对应,所有三个范围的长度均为1,并且仅由1个元素分隔。在我的情况下,唯一的限制是距离(first3,last3)&gt; =距离(first1,last1)+距离(first2,last2)(我肯定可以放松更多的计算费用)。

我的应用是生成每个独特的排列而不是它的反转。代码在这里:

http://howardhinnant.github.io/combinations.html

具体适用的函数是combine_discontinuous3(创建组合),以及它在reversible_permutation :: operator()中的使用,它创建了排列。

这不是针对您的问题的现成的打包解决方案。但它是一个可用于解决问题概括的工具集。同样,对于您确切的简单问题,我建议其他人提供的更简单的解决方案。

答案 2 :(得分:0)

请记住您想要固定号码的地方。从阵列中删除它们。 像往常一样生成排列。每次排列后,将固定数字插入它们应出现的位置,然后输出。

答案 3 :(得分:0)

如果您有一组数字{4,3,2,1,5},并且您知道3和1不会被置换,那么您可以将它们从集合中取出并为{4生成一个powerset ,2,5}。之后你要做的就是在功率组中为每组设置插入1和3各自的位置。

我发布了similar question,在那里你可以看到powerset的代码。