给定范围 [m, n],其中 0 <= m <= n <= 2147483647,返回此范围内所有数字的按位与(包含 m, n 两端点)。
- 这题解法让我惊叹,竟然如此简洁优美!!
- 二整数与运算,0&0 = 0; 0&1 = 0; 1&0 = 0; 1&1 = 1;
- 0与任何数与运算均为0,因此二个整数只有对应位全1 进行与运算结果才是1。
- 法一 移位--寻找公共前缀
int rangeBitwiseAnd(int m, int n) {
int shift = 0;
// 找到公共前缀
while (m < n) {
m >>= 1;
n >>= 1;
++shift;
}
return m << shift;
}
- 法二 Brian Kernighan 算法
- 位移相关的算法叫做「Brian Kernighan 算法」,它用于清除二进制串中最右边的 11。
- 关键在于我们每次对 number 和 number−1 之间进行按位与运算后,number 中最右边的 1会被抹去变成 0。
- 其思想是,对于给定的范围 [m,n](m<n),我们可以对数字 n 迭代地应用上述技巧,清除最右边的 1,直到它小于或等于 m,此时非公共前缀部分的 1 均被消去。因此最后我们返回 n 即可。
int rangeBitwiseAnd(int m, int n) {
while (m < n) {
// 抹去最右边的 1
n &= (n - 1);
}
return n;
}