201. 数字范围按位与
[此处请插入:二进制公共前缀匹配过程示意图]
✨核心逻辑
本题采用 寻找公共前缀(位移法) 的策略:
- 核心规律:对区间
[left, right]内的所有数字进行按位与运算,结果实际上等于left和right的二进制公共前缀,然后在后面补上足够数量的0。 - 寻找公共前缀:我们可以通过一个
while循环,不断将left和right同时向右移位(相当于除以 2)。当left < right时,说明它们的二进制在低位还不一致,继续移位。 - 记录补零位数:每次移位时,使用变量
num记录移位的次数。当left和right最终相等时,left就是它们的公共二进制前缀。 - 还原结果:最后,将公共前缀
left向左移动num位(相当于补num个0),即得到最终按位与的结果。
🔥代码实现(含详细变量注释)
class Solution {
public int rangeBitwiseAnd(int left, int right) {
// num:记录 `left` 和 `right` 同时向右移位(除以 2)的次数
// 这个次数也代表了最终结果需要在公共前缀后面补的 `0` 的个数
int num = 0;
// 只要 left 小于 right,说明它们的二进制在低位还有差异
// 需要不断缩小范围,寻找它们的公共高位前缀
while (left < right) {
left >>= 1; // left 除以 2,舍弃最低位
right >>= 1; // right 除以 2,舍弃最低位
num++; // 记录已经移位的次数
}
// 循环结束时,left 和 right 相等,即找到了公共前缀
// 将公共前缀左移 num 位(补上 num 个 0),即为该区间按位与的最终结果
return left << num;
}
}
- ⏱️复杂度分析
时间复杂度:O(log N)(或视为常数时间 O(1))。循环执行的次数取决于 left 和 right 的最大二进制位数。在 Java 的 int 类型下,最坏情况下循环最多执行 32 次,效率极高。
空间复杂度:O(1),只使用了一个额外的整型变量 num 来记录移位次数
🔍总结一下:
这类题真的很考验数学逻辑:
这道题最本质、最核心的灵魂如下:
假设从数字A到数字B,二者的二进制公共前缀是X,不公共的称为Y,也就是说,你从A到B,不看公共前缀X,A的不公共的Y部分一定经历了从0到1和从1到0的变化,才能成为B
