【问题标题】:Permutations with some fixed numbers一些固定数字的排列
【发布时间】:2011-01-19 21:07:07
【问题描述】:

如果我在指定位置需要一些字符/数字,如何有效地生成数字(或单词中的字符)的排列?

例如生成所有数字,其中 digit 3 位于第二个位置,digit 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} 的数组并将其循环发布到该函数,但是如何处理固定位置?

【问题讨论】:

    标签: c++ algorithm permutation


    【解决方案1】:

    生成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
    

    【讨论】:

    • 所以我应该创建下一个数组 {0, 2, 4} 并在将生成的排列放回数字时使用它?
    • 只需将{2,4,5} 放入数组中即可。我已经发布了示例代码。 (很好的练习;)
    【解决方案2】:

    我已经阅读了其他答案,我相信对于您的具体问题,它们比我的要好。但是,如果有人需要通用解决方案来解决您的问题,我会回答。

    我最近需要生成 3 个独立的连续范围 [first1, last1) + [first2, last2) + [first3, last3) 的所有排列。这对应于您的情况,所有三个范围的长度均为 1,并且仅由 1 个元素分隔。就我而言,唯一的限制是 distance(first3, last3) >= distance(first1, last1) + distance(first2, last2) (我确信可以通过更多的计算费用来放松)。

    我的应用程序是生成每个唯一的排列,但不是它的反转。代码在这里:

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

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        如果您有一组数字 {4,3,2,1,5} 并且您知道 3 和 1 不会被置换,那么您可以将它们从集合中取出并生成 {4 的幂集, 2, 5}。之后,您只需将 1 和 3 插入到电源组中每个组的各自位置即可。

        我发布了similar question,您可以在其中看到 powerset 的代码。

        【讨论】:

        • 生成 powerset 需要指数级的内存。使用标准 C++ 函数 next_permutation,这可以通过恒定数量的额外内存来完成。
        • @larsmans,我在这里有点困惑......我简要查找了question in which the powerset is generated using next_permutation,运行时间似乎是:O(n! *2^n)。 Generating a powerset takes O(n*2^n),所以看起来你要么节省运行时间,要么节省内存。
        • 首先,OP 的问题是生成所有 permutations,而不是 subsetscombinations,因此 powerset 是在这里没用。接下来,生成所有排列的时间复杂度由排列数限制,即 n! = O(n ^ n)。使用next_permutation 循环对于时间复杂度n 的问题来说是最佳的! * O(n) = O(n ^ (n + 1)) = O(n ^ n) 和常数空间。
        猜你喜欢
        • 2012-08-22
        • 1970-01-01
        • 1970-01-01
        • 2016-03-25
        • 2015-10-11
        • 1970-01-01
        • 2016-03-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多