给定范围 [m, n],其中 0 <= m <= n <= 2147483647,返回此范围内所有数字的按位与(包含 m, n 两端点)。
示例 1:
输入: [5,7]
输出: 4
示例 2:
输入: [0,1]
输出: 0
解题思路:统计两个数二进制表示的公共前缀
因为假设两个数在第i位前面都相同,第i位一个为0,一个为1,那么这两个数之间一定存在一个数,这个数的第i位为1,且后面的都是0。这样 ‘按位与’ 之后i位以及之后就都是零了。
所以求两个数的公共前缀即可。
通过两个数不断右移,直到两个数相等。
再左移对应的位数
Java代码如下:
public int rangeBitwiseAnd(int m, int n) {
int i = 0;
while (m != n){
m >>= 1;
n >>= 1;
i ++;
}
return m << i;
}
补充:最直观的解决方案就是迭代范围内的每个数字,依次执行按位与运算,得到最终的结果,但此方法在 [m,n] 范围较大的测试用例中会因超出时间限制而无法通过。
迭代范围内的所有数会导致超时:
public int rangeBitwiseAnd(int m, int n) {
int result = m;
while (m < n)
result &= m++ + 1;
return result;
}
但注意到,当按位与的结果为0时,后面的数再执行,结果也都为0.所以当按位与的结果为0时就可以终止循环:
public int rangeBitwiseAnd(int m, int n) {
int result = m;
while (m < n && result != 0)
result &= m++ + 1;
return result;
}
如此用时604毫秒,并未超时。