问题描述:
给定范围 [m, n],其中 0 <= m <= n <= 2147483647,返回此范围内所有数字的按位与(包含 m, n 两端点)。
示例 1:
输入: [5,7]
输出: 4
示例 2:
输入: [0,1]
输出: 0
解题思路:
首先使用暴力解法
class Solution {
public:
int rangeBitwiseAnd(int m, int n) {
int res=m;
for(int i=m;i<=n;i++){
res = res&i;
}
return res;
}
};
超时
下面开始采用另外一种解法
当一个数+1时,总会有这么一个规律“某一位后的数字,全部被置为相反数”。举个例子:
010111 + 1 = 011000,则010111 & 011000 = 010000。那么,x & (x+1) 后几位相反数的“与操作”,结果总为0。
比如5,6,7
5:101
6:110
7:111
从m依次&到n,这样的话我们只用求出m和n的右边公共部分,
5&6&7=100,实际上只用5和7的右边公共部留下了其余部分全部为0
class Solution {
public:
int rangeBitwiseAnd(int m, int n) {
int offset=0;
while(m!=n){
m>>=1;
n>>=1;
offset++;
}
return n<<offset;
}
};
这里是我们依次右移m和n,求出公共前缀,当跳出循环的时候,m=n,在5,6,7的例子中最后m=n=1;
offset是统计右移的位数。最后将n或者m左移即可。