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.
1.我的答案 真的挺啰嗦挺麻烦的
我的想法是这样的:
(1). 假设m = 101, 则若n>=1000,AND的和都是0;因此先判断,若n>=1000,则将n=111;
(2). 可以先列个范围观察一下
c b a
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
可以看到,若n - m相差值大于1,则a位一定是0; 若n-m>=2,(b位上只有两个1,两个0,当大于2时,肯定会有一个0包含进来),则b位也会是0;
以此类推,我们就可以把判断的位范围缩小到 n-m < 2^x 范围内;
比如 m = 5, n = 7; 则 n - m >=2, 则只需从c位开始往高位判断,此时将只有c位为1的数100分别与n,m相&,若头尾都是1,则[m,n]范围内的数一定在c位也是1,则将sum = 100|sum;
然后再判断比c位高的数的位;因此判断范围就是[m位数-1,x] (最右边从0开始) 因此最糟糕的为O(31).
trick:当m = 2^31-2, n = 2^31-1时,用if(n >= (1<<count)) return 0; 会出错;因为1<<31 会小于 n(= 2^31-1),因此这里改为判断 if(n <= (1 <<count) -1) 避免错误。
class Solution {
public:
int rangeBitwiseAnd(int m, int n) {
if(m == n) return m;
int count = 0;
int num = m;
while(num > 0){
count++;
num >>= 1;
}
if(n <= ((1 << count)-1))
n = n;
else
return 0;
int cou = n - m;
int count2 = 0;
while(cou > 0){
count2++;
cou >>= 1;
}
int sum = 0;
for(int i = count2; i <= count-1; i++){
int res = 1 << i;
if((m & res) == res && (n & res) == res){
sum |= res;
}
}
return sum;
}
};
class Solution {
public:
int rangeBitwiseAnd(int m, int n) {
int trans = 0;
while(m != n)
{
++ trans;
m >>= 1;
n >>= 1;
}
return m << trans;
}
};
或者是这样的
int rangeBitwiseAnd(int m, int n) {
return (n > m) ? (rangeBitwiseAnd(m/2, n/2) << 1) : m;
}