题目
给定范围 [m, n],其中 0 <= m <= n <= 2147483647,返回此范围内所有数字的按位与(包含 m, n 两端点)。
思路
一开始,本来也想从头到尾遍历一遍,然后直接得出结果,然后就超时了。
然后,就看了一下题解,发现真的是妙啊。首先,按位与,得是两个数字都是1结果才为1。所以,假设结果中,假设对应的二进制位为1,那么在所有的数字中,这个位置的数字应该都是1。
这两个数字,假设说m==n,那不必说,结果直接就可以得出来,那如果是n<m这种情况,就要分开考虑一下,我们都知道,相邻两个数字的至少有一位是不同的,即按位与结果是0。既然这样,有很多按位与是没有必要计算的,我们只需要知道两个数字的最大公共二进制前缀即可,其余的,因为不是公共的,总会在过程中被置为。
代码
class Solution {
public int rangeBitwiseAnd(int m, int n) {
int count = 0;
// 找到公共前缀
while (m < n) //两个数必须得不相同
{
//每次都往右移动一位,再判断剩下的数字是否相等
m >>= 1;
n >>= 1;
++count;//每次不相等,就加1,,这就是不相同的位数
}
//将m的小数点往左移动,把不相同的部分给丢弃掉
return m << count;
}
}
结果
虽然是简单题,但是收获很多。