给定范围 [m, n],其中 0 <= m <= n <= 2147483647,返回此范围内所有数字的按位与(包含 m, n 两端点)。
示例 1:
输入: [5,7] 输出: 4
示例 2:
输入: [0,1] 输出: 0
解题思路:
二进制数的最长公共前缀,位运算。
为什么这个问题类似于求最长公共前缀,证明如下:
1. [m,n]内的所有数的最长公共前缀都是一样的,如果有一个不是,这个数必然在这个范围之外。
2. 如果我们不考虑这些前缀,已经将前缀pre_n,pre_m删除,那么剩下的部分必然是满足 n的最高位是1,而m的最高位是0。
3. 可以假设剩余位的个数是length,那么 n>=2^(length-1)必然存在,也就是说现在的[m,n]必然存在2^(length-1),这个数字的特征是最高位为1,而其余位是0。由于m的最高位是0,所以当前的[m,n]与运算必然是0。
4. 再返回到原来的[m,n]与运算。很容易发现就是pre_n<<length的结果。
class Solution { public: int rangeBitwiseAnd(int m, int n) { int count = 0; while (m != n) { m >>= 1; n >>= 1; ++count; } return m << count; } }; |