给定范围 [m, n],其中 0 <= m <= n <= 2147483647,返回此范围内所有数字的按位与(包含 m, n 两端点)。
示例 1:
输入: [5,7]
输出: 4
示例 2:
输入: [0,1]
输出: 0
这个题精髓在于n的二进制位比m二进制最左边的1高时,&的结果必然为0,受此思想启发,给出两种解答方案
class Solution {
private:
int getLen(int m) //获取二进制的位数
{
int len = 0;
while(m)
{
len++;
m>>=1;
}
return len;
}
public:
int rangeBitwiseAnd(int m, int n) {
if(getLen(m) != getLen(n)) return 0;
int numRes = n;
for(int i = n-1 ; i >= m; i--)
{
if(numRes == 0) return 0;
numRes &= i;
}
return numRes;
}
};
1、获取二进制的位数,从大到小不断进行与运算
class Solution {
public:
int rangeBitwiseAnd(int m, int n) {
//n&(n-1)会把最后一个1后面所有位都置为0,有点类似找m和n二进制的公共前缀
int cnt = 0; //记录右移的次数
while(m != n) //直到m和n相同
{
if(m == 0) return 0;
m >>= 1;
n >>= 1;
cnt++;
}
return m << cnt;
}
};
2、二进制最高位相同时,这个1会保存,然后比较右一位,相同也保留… 所以只需要m n 同时右移到相等时 m n的值就是&后能保留的位数,然后左移回来就是最后的值。