【问题标题】:Permuting All Possible (0, 1) value arrays排列所有可能的 (0, 1) 值数组
【发布时间】:2010-09-17 12:09:10
【问题描述】:

我正在编写一个算法来生成此类数组的所有可能排列:

n = 长度
k = 数组中 1 的个数

所以这意味着如果我们有 k 个 1,我们将在数组中有 n-k 个 0。

例如: n = 5; k = 3;

所以显然这个数组有 5 种选择 3 种可能的排列,因为
n!/(k!(n-k)!
5!/(3!2!) = (5*4)/2 = 10
数组的可能值

以下是所有值:
11100
11010
11001
10110
10101
10011
01110
01101
01011
00111

我猜我应该使用递归算法,但我只是没有看到它。我正在用 C++ 编写这个算法。

任何帮助将不胜感激!

【问题讨论】:

标签: c++ algorithm


【解决方案1】:

只需从00111 开始,然后使用std::next_permutation 生成其余部分:

#include <algorithm>
#include <iostream>
#include <string>

int main()
{
    std::string s = "00111";
    do
    {
        std::cout << s << '\n';
    }
    while (std::next_permutation(s.begin(), s.end()));
}

输出:

00111
01011
01101
01110
10011
10101
10110
11001
11010
11100

【讨论】:

  • 如果他需要实现算法,据我了解 OP,这将无济于事。
  • OP 说这不是功课,所以应该鼓励标准库,而不是反对。
  • 拒绝投票。看到他的评论太晚了,那不是硬件。
【解决方案2】:

您可以将组合拆分为以 1 开头的组合 (n-1, k-1) 和以 0 开头的组合 (n-1, k)。

这本质上是recursive formula for the choose function

【讨论】:

    【解决方案3】:

    你想要的实际上是一个组合,因为 1 和 0 是无法区分的,因此它们的顺序无关紧要(例如 1 1 1 vs 1 1 1)。

    我最近不得不自己重写一个组合函数,因为我的初始版本是以非常简单的方式递归编写的(选择一个元素,获取剩余数组的所有组合,将元素插入到各个位置)并且表现不佳好吧。

    我搜索了 StackOverflow,看到 this answer 中的图片点亮了我头顶的标志性灯泡。

    【讨论】:

    • 实际上也不是组合,是吗?因为 1 和 0 是彼此区分的111000 != 010101 但这些将被视为相同的组合。
    • 哦,我知道它是如何组合的。可以从 {1, 2, 3, 4, ... n} 中选择 k,这将是结果组合中 1 的索引。
    【解决方案4】:

    如果您想递归执行此操作,请注意您想要的排列集等于所有以"1" 开头的排列,以及所有以"0" 开头的排列。所以在计算(n,k)时,你将递归(n-1,k-1)(n-1,k),特殊情况是k = 0k = n

    这种递归是二项式系数作为帕斯卡三角形中的值出现的原因。

    【讨论】:

      【解决方案5】:

      作业和递归算法?好的,给你:

      基本情况: 您有两个元素,将它们命名为“a”和“b”并产生串联 ab,然后是 ba。

      步骤:如果您的第二个元素长于 1,请将其拆分为第一个字段/字母和另一部分,并将其作为参数递归传递给函数本身。

      这适用于任何字符串和数组。

      【讨论】:

        【解决方案6】:

        它大约是 0-1 排列,因此迭代递增一个整数可能更有效,如果它有所需的位数,打印出它的二进制表示。

        这里是一个草图:

        void printAllBinaryPermutations(int k, int n)  
        {  
          int max = pow(2, n) - 1;  
          for(int i=0; i<=max;i++)  
          {  
            if(hasBitCountOf(i, k)) // i has k 1's?  
            {  
              printAsBinary(i, n);  
            }  
          }  
        }  
        
        
        bool hasBitCountOf(int v, int expectedBitCount)  
        {  
            int count = 0;  
            while(v>0 && count<= expectedBitCount)  
            {  
                int half = v >> 1;  
                if(half<<1 != v)  
                {  
                    // v is odd  
                    count++;  
                }  
                v = half;  
            }  
        
            return count==expectedBitCount;  
        }  
        
        
        void printAsBinary(int number, int strLen)  
        {  
          for(int i=strLen-1; i>=0; i--)  
          {  
            bool is0 = (number & pow(2,i)) == 0;  
            if (is0)  
            {  
              cout<<'0';  
            }  
            else  
            {  
              cout<<'1';  
            }  
          }   
        
          cout<<endl;  
        
        }
        

        【讨论】:

        • 即使我迭代的组合比实际生成的多得多,这个解决方案应该更有效,因为这是简单的位移和递增,并且没有堆栈吹递归。
        【解决方案7】:

        我不确定这是否有帮助,而且它只是一些奇怪的伪代码,但这应该会给你想要的输出。

        permutation (prefix, ones, zeros, cur) {
            if (ones + zeros == 0) output(cur);
            else {
                if (cur != -1) prefix = concat(prefix,cur);
                if (ones > 0) permutation(prefix, ones - 1, zeros, 1);
                if (zeros > 0) permutation(prefix, ones, zeros - 1, 0);
            }        
        }
        
        permutation(empty, 3, 2, -1);
        

        问候
        back2dos

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-03-27
          • 1970-01-01
          • 2015-08-22
          • 1970-01-01
          • 1970-01-01
          • 2017-10-14
          • 1970-01-01
          相关资源
          最近更新 更多