【问题标题】:Finding next bigger number with same number of set bits用相同数量的设置位找到下一个更大的数字
【发布时间】:2014-10-27 19:04:43
【问题描述】:

我正在解决一个给定数字 n 的问题,我必须找到具有相同数量设置位的下一个更大的元素。在网上搜索时,我发现了一段有趣的代码,只需几行代码(BIT MAGIC)here

unsigned nexthi_same_count_ones(unsigned a) {
  /* works for any word length */
  unsigned c = (a & -a);
  unsigned r = a+c;
  return (((r ^ a) >> 2) / c) | r);
}

但我想了解该算法的基本逻辑,即它将始终有效。所有边界情况都会得到妥善处理。

谁能用简单的步骤解释一下逻辑。

谢谢

【问题讨论】:

标签: c algorithm bit-manipulation


【解决方案1】:

在下一个更大的数字中,1s 最右边的最左边的1 与左边的0 交换位置,而其余的1s 移动到最右边。

  • 代码隔离最低1
  • 将其添加到a(使进位涟漪传递到下一个更高的0,反转所有这些位)
  • ex-or 得到最不重要的运行,向左扩展一个位置。
  • 将其向右移动两个位置使其左边界在原始边界的右侧移动一个位置 (从高处给那个0留位子),
  • 除以最低的1 会为0 提供空间,因为a 右端的空间更多。

【讨论】:

  • 向左扩展一个位置(在第三个项目符号中)是什么意思?
  • least significant run of ones, extended one position to the left最不重要的一串,包括左边的被另一个一个替换。
  • 这里有一些例子可以帮助你更好地理解。
【解决方案2】:

假设我们有一个位模式,例如

111100111 - 表示十进制的 487

要生成下一个最大整数,同时保留输入中 0 和 1 的数量,我们需要从输入右侧找到第一个 0 位,然后是 1,我们需要将该位切换为1. 然后我们需要将该翻转点右侧的 1 的数量减少 1,以补偿我们从 0 切换到 1 的位。

我们的新位模式将变为 111101011 - 491(十进制)(我们保留了设置的位数,但未根据输入设置)

int getNextNumber(int input)
{
    int flipPosition=0;
    int trailingZeros=0;
    int trailingOnes=0;
    int copy = input;

    //count trailing zeros
    while(copy != 0 && (copy&1) == 0 )
    {
        ++trailingZeros;

        //test next bit
        copy = copy >> 1;
    }

    //count trailing ones
    while(copy != 0 && (copy&1) == 1 )
    {
        ++trailingOnes;

        //test next bit
        copy = copy >> 1;
    }

    //if we have no 1's we cannot form another patter with the same number of 1's
    //which will increment the input, or if we have leading consecutive
    //zero's followed by consecutive 1's up to the maximum bit size of a int
    //we cannot increase the input whilst preserving the no of 0's and
    //1's in the original bit pattern
    if(trailingZeros + trailingOnes  == 0 || trailingZeros + trailingOnes == 31)
        return -1;

    //flip first 0 followed by a 1 found from the right of the bit pattern
    flipPosition = trailingZeros + trailingOnes+1;
    input |= 1<<(trailingZeros+trailingOnes);

    //clear fields to the right of the flip position
    int mask = ~0 << (trailingZeros+trailingOnes);
    input &= mask;

    //insert a bit pattern to the right of the flop position that will contain
    //one less 1 to compensate for the bit we switched from 0 to 1
    int insert = flipPosition-1;
    input |= insert;

    return input;
}

【讨论】:

  • 的情况下,它不应该大于 31 而不是等于...我的意思是考虑第 31 位为 1,其他位为 0。在那case 将是 32,对吗?我错过了什么吗?
  • 见上面的评论。
猜你喜欢
  • 1970-01-01
  • 2016-03-27
  • 1970-01-01
  • 2012-03-11
  • 2022-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多