给定范围 [m, n],其中 0 <= m <= n <= 2147483647,返回此范围内所有数字的按位与(包含 m, n 两端点)。
Given a range [m, n] where 0 <= m <= n <= 2147483647, return the
bitwise AND of all numbers in this range, inclusive.
思路:
- 2147483647的二进制为31位的1组成,最粗暴的做法是直接用它递归地和所有位于[m, n]之间的数进行按位与,但是这样会超过时间限制。
- 其实只要某个数二进制的某一位为0,其他数与之按位与,该位都会为0,对于[m, n]范围内的连续整数,只需要找出m和n的最长公共前缀即可。
解法:
- 位移法:将m和n同时向右位移,直到两数相等,再将它们任意一个向左位移同样位数即可;
- Brian Kernighan算法:n和(n-1)按位与即可去除二进制中最后一个1,所以对于[m, n],每次让n和(n-1)按位与,直到m为止即可。
Python:
# 位移法
def rangeBitwiseAnd(m, n):
shift = 0
while m < n:
m >>= 1
n >>= 1
shift += 1
return m << shift
# Brain Kernighan
def rangeBitwiseAnd(m, n):
while m < n:
n &= n - 1
return n
C++:
// 位移法
int rangeBitwiseAnd(int m, int n)
{
int shift = 0;
while (m < n)
{
m >>= 1;
n >>= 1;
shift ++;
}
return m << shift;
}
// Brain Kernighan
int rangeBitwiseAnd(int m, int n)
{
while (m < n)
{
n &= n - 1;
}
return n;
}