范围[a,b]中的最小数字,最大数量为' 1'在二进制表示中

时间:2015-01-12 17:11:14

标签: algorithm bit-manipulation

给定范围[a,b](包括两者)我需要找到最小数字,其中二进制表示的最大数量为1。我目前的方法是找到从a到b的所有数字中设置的位数,并跟踪最大值。 然而,这是非常慢的,任何更快的方法?

2 个答案:

答案 0 :(得分:2)

让我们找到a和b中不同的最重要的位。它将是0 in a,1 in b。如果我们将右边的所有其他位置于1 - 结果数字仍然在范围内[a; B]。它将是表示最大数量为1的单个数字。

修改即可。该算法的结果总是返回n-1位设置为1的数字,其中n是可以改变的位数。正如评论中所指出的 - 如果b中的所有n位都设置为1,则存在一个错误。这是固定的代码片段:

int maximizeBits(int a, int b) {
    if (a == b) {
        return a;
    }
    int m = a ^ b, pow2 = 1; // MSB of m=a^b is bit that we need to find
    while (m > pow2) { // Set other bits to 0
        if ((m & pow2) != 0) {
            m ^= pow2;
        }
        pow2 <<= 1;
    }

    int res = a | (m - 1); // Now m is in form of 2^n and m - 1 would be mask of n-1 bits
    if ((res | b) <= b) { // Fix of problem if all n bits in b are set to 1
        res = b;
    }
    return res;
}

答案 1 :(得分:2)

你可以用Jarlax&#39;替换循环。通过&#34;并行后缀OR&#34;回答,像这样

uint32_t m = (a ^ b) >> 1;
m |= m >> 1;
m |= m >> 2;
m |= m >> 4;
m |= m >> 8;
m |= m >> 16;
uint32_t res = a | m;
if ((res | b) <= b)
    res = b;
return res;

它通常使用ceil(log(k))步骤推广到不同大小的整数。初始测试a == b不是必需的,a ^ b将为零,因此m为零,因此无论如何都不会发生任何有趣的事情。


或者,这是一种完全不同的方法:将最低0改为1,直到不再可能为止。

unsigned x = a;
while (x < b) {
    unsigned newx = (x + 1) | x; // set lowest 0
    if (newx <= b)
        x = newx;
    else
        break;
}
return x;