Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND of all numbers in this range, inclusive.
For example, given the range [5, 7], you should return 4.
算法一:使用异或
一个范围内所有的数作位与运算,结果是高位相同部分保存不变,低位为0.
我们要做的是,如何求出这个分界位置。
不需要对范围中每个数,作位与运算,仅需对两个端点作异或运算。
异或运算是,相同位将为0,不同位则为1.
对异或运算结果,从左向右,找到第一个为1的位置。则此位置,为变和不变的分界点。自此位置往右,将是变化部分。在与运算的结果将为0.
然后从此位置将右边的部分全部置为1. 最后取反,即得到掩码。
在将右边位置填充为1的思路为,将其向右移1位,再和自己作或运算。此时,完成向右填充了1位。现在已经有连续2位肯定为1了。
故可以再往右移2位,与自己作或运算。至此完成填充4个bit位。
通过范围的端点,求出左边第一个相异位置,而不需要对每个数进行运算,原因如下:
通过端点求出的左边不变化bit位中,如果对其中一位作一下变动(取反),则得到的新数,将不在这两个端点的范围内。
class Solution { public: int rangeBitwiseAnd(int m, int n) { int mask = m ^ n; mask |= mask >> 1; mask |= mask >> 2; mask |= mask >> 4; mask |= mask >> 8; mask |= mask >> 16; return m & ~mask; } };
也可以不填充过程写成循环。但要注意的事,对32位的整数右移右移32位时,结果是未定义的,而不是0.
在leetcode中,右移32位,竟然返回的是1.
故需要在循环加个退出条件:shifts < 32。
class Solution { public: int rangeBitwiseAnd(int m, int n) { int mask = m ^ n; int shifts = 1; while (shifts < 32 && mask >> shifts) { mask |= mask >> shifts; shifts <<= 1; } return m & ~mask; } };
寻找左边第一个开始相异的位置,可以用码码逐位进行偿试。直到相等为止。
class Solution { public: int rangeBitwiseAnd(int m, int n) { int mask = -1; while ((m & mask) != (n & mask)) mask <<= 1; return m & mask; } };
同时相右移位,将不相等位移掉。直到相等。最后向左移位恢复。
class Solution { public: int rangeBitwiseAnd(int m, int n) { int shifts = 0; while (m != n) { m >>= 1; n >>= 1; ++shifts; } return m << shifts; } };
class Solution { public: int rangeBitwiseAnd(int m, int n) { return n != m ? rangeBitwiseAnd(m>>1, n>>1) << 1 : n; } };
版权声明:本文为博主原创文章,未经博主允许不得转载。
Bitwise AND of Numbers Range -- leetcode
原文地址:http://blog.csdn.net/elton_xiao/article/details/46843751