欢迎访问LeetCode题解合集
题目描述
给你两个整数 left
和 right
,表示区间 [left, right]
,返回此区间内所有数字 按位与 的结果(包含 left
、right
端点)。
示例 1:
输入:left = 5, right = 7
输出:4
示例 2:
输入:left = 0, right = 0
输出:0
示例 3:
输入:left = 1, right = 2147483647
输出:0
提示:
0 <= left <= right <= 2^31 - 1
题解:
找规律。
我们只观察后面 6
位二进制。假设 l = 5, r = 7
,那么:
5 0 0 1 0 1
6 0 0 1 1 0
7 0 0 1 1 1
可以发现,5
和 7
有一部分公共前缀 0 0 1
假设 l = 5, r = 8
,那么:
5 0 0 1 0 1
6 0 0 1 1 0
7 0 0 1 1 1
8 0 1 0 0 0
可以发现,5
和 8
有一部分公共前缀 0
而对于 l
和 r
,如果它们有公共的前缀,那么对于 [l + 1, r - 1]
,它们一定有相同的公共前缀。对于剩下的部分,0
和 1
都有,按位与 肯定为 0
。
所以,这题就是求 l
与 r
的公共前缀。
时间复杂度:$O(1)$
额外空间复杂度:$O(1)$
class Solution {
public:
int rangeBitwiseAnd(int left, int right) {
if( left == right ) return left;
int ret = 0, l, r;
for ( int i = 31; i >= 0; --i ) {
l = left >> i;
r = right >> i;
if( l == r ) {
if( l & 1 ) ret |= 1 << i;
} else break;
}
return ret;
}
};
/*
时间:8ms,击败:84.59%
内存:5.9MB,击败:41.13%
*/
当然,也可以将 r
右边的 1
移掉,当 l == r
时停止。
class Solution {
public:
int rangeBitwiseAnd(int left, int right) {
while ( right > left )
right &= right - 1;
return right;
}
};
/*
时间:8ms,击败:84.59%
内存:5.9MB,击败:55.58%
*/