按位移位以在 C 中生成所有可能的排列 [重复]

Posted

技术标签:

【中文标题】按位移位以在 C 中生成所有可能的排列 [重复]【英文标题】:Bitwise shift to generate all possible permutations in C [duplicate] 【发布时间】:2011-11-19 02:20:10 【问题描述】:

可能重复:Creating multiple numbers with certain number of bits set

我正在尝试编写一些代码,通过移动位将每个可能的数字组合放入一个数组中。

例如,我想找到所有可能的 3 位组合(其中一个数字的最大值可以是 6),数组应该包含:

000111 001011 001101 001110 010011 010101 010110 011001 011010 011100 100011

等等……

根据我的解释,当最后一个位置位为 1 时,我们将数字移位 1 (x >> 1) 并在开头添加 1。但是,我不确定如何对其余部分进行编码。我正在使用 C 来写这个。

另外 - 据我所知,这是一个 colex 序列,但是,如果有另一个序列会给我相同的最终结果(具有约束的所有可能的 k 位组合的数组),我会全力以赴N)。

【问题讨论】:

复制Creating multiple numbers with certain number of bits set,Generate all binary strings of length n with k bits set。 【参考方案1】:

您可以通过递归生成序列来解决这个问题。

让我们定义一个递归函数f(int index, int bits, int number),它将接受当前位的index和剩余的bits的数量,以及到目前为止生成的number。然后,您可以选择将当前位设置为 1 或 0,并从那里递归。

总的来说,时间复杂度应该是O(序列数),或者O(N选择B),其中N是位数,B是设置为1的位数。

函数是这样的:

void f(int index, int bits, int number) 
    if (index == 0) 
        if (bits == 0)    // all required bits have been used
            emit_answer(number); // chuck number into an array, print it, whatever.
           
        return;
       

    if (index-1 >= bits)   // If we can afford to put a 0 here
        f(index-1, bits, number);
       

    if (bits > 0)   // If we have any 1s left to place
        f(index-1, bits-1, number | (1 << (index-1)));
       


// to call:
f(6, 3, 0); 

对于N,B = 6,3,输出与您的匹配,并且按排序顺序排列。链接到工作示例:http://codepad.org/qgd689ZM

【讨论】:

谢谢@evgeny。玩了这个,学到了一些东西。只是关于欺骗 - 对于那些感兴趣的人,请点击欺骗链接并阅读斯坦福资源。对我帮助很大。【参考方案2】:

可能有一种更有效的方法,但您可以循环遍历数字并拒绝位数不为 3 的数字吗?位计数见this answer。

【讨论】:

然后你必须经历 2^N 组合,这可能会变得很慢。再说一次,他只需要 6 位,所以应该没问题。 这很慢,O(2^N) 就像 quasiverse 指出的那样。我的解决方案应该生成所有有效序列而不会产生任何浪费。 好的,当然。它是 O(2^6)。不过,我认为如果速度真的是一个问题,他可以提前计算数字并保存它们。那么它将是 O(1) :-p 更不用说这个解决方案相对于其他一些解决方案的可读性了。 耸耸肩【参考方案3】:

不需要任何花哨的递归。一些简单的数学运算就足够了(需要除以一个总是 2 的幂的值)。

函数 nextBits(ByVal prevVal As Integer) Dim lsOne As Integer = ((prevVal - 1) And Not prevVal) + 1 将 nextZero 调暗为整数 = (prevVal + lsOne) 而不是 prevVal Dim lowBits As Integer = ((nextZero \ lsOne \ 2) - 1) 返回 prevVal + lsOne + lowBits 结束功能

简单又好用。

【讨论】:

呃......我的大脑被代码伤害了。另外,什么是 \ 运算符?也许解释一下为什么会有所帮助。 请在代码中添加更多解释。 OP 似乎对 C 代码感兴趣,而这更像是 VB-ish。 对不起。我在 VB.NET 中测试了算法并复制/粘贴了代码。相同的算法应该很容易适应任何其他通用语言。我忘记了人们不知道的 VB.NET 的一个方面是它使用不同的运算符进行小数除法和整数除法,所以15 / 4 产生 3.75,但 15 \ 4 产生 3。Python 等价物是// 运算符,而 C 等效项是带有整数操作数的 / 运算符(如果想要将两个整数相除以获得小数结果,则需要显式强制转换或强制转换)。 @Hritik:我认为这个问题看起来像是家庭作业,所以我想我想引导这个人朝着正确的方向前进,而不是给出一个他们可以在没有思考或理解的情况下使用的解决方案。尝试一些不同的值并查看每个变量最终以二进制形式显示的内容应该可以揭示发生了什么。

以上是关于按位移位以在 C 中生成所有可能的排列 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何从所有排列中生成所有可能的组合?

R从n个元素的字符向量中生成大小为m的所有可能组合[重复]

在 R 中生成列表的所有不同排列

为啥java中生成32位随机ID永远不会重复?

如何在 PHP 中生成字符串的所有排列?

在目标c中生成组合的有效方法[重复]