給定範圍 [m, n] (0 ≤ m ≤ n ≤ 2³¹-1),返回該範圍內所有整數的按位與結果。
範例:[5,7] → 5&6&7 = 4 (101 & 110 & 111 = 100)
觀察二進位:
5: 101 6: 110 7: 111 &: 100 = 4
結果等於 m 和 n 的公共左側前綴(高位),低位全為 0。
原因:範圍內必包含某位從 0 變 1 再變 0 的完整週期,導致該位及更低位按位與結果為 0。只有 m 和 n 高位完全相同的位才可能保持 1。
不斷右移 m 和 n 直到相等,記錄右移次數 shift,最後左移回去:
class Solution {
public:
int rangeBitwiseAnd(int m, int n) {
int shift = 0;
while (m != n) {
m >>= 1;
n >>= 1;
++shift;
}
return m << shift;
}
};
m=5 (101), n=7 (111)
| 輪次 | m | n | shift |
|---|---|---|---|
| 0 | 101 | 111 | 0 |
| 1 | 10 | 11 | 1 |
| 2 | 1 | 1 | 2 |
返回 1 << 2 = 100 (4) ✓
反覆清除 n 的最低置位 1,直到 n ≤ m:
int rangeBitwiseAnd(int m, int n) {
while (n > m) {
n &= (n - 1); // 清除最低位 1
}
return m & n;
}
原理:n 的最低位 1 代表某位在範圍內會翻轉,清除它模擬範圍縮小。
m=0 直接返回 0;m=n 返回 mLeetCode 201 是位運算規律題。核心洞察:範圍按位與 = 兩端點的公共高位前綴 + 低位全 0。右移法代碼極簡,Kernighan 法利用 n & (n-1) 清除最低位 1 技巧更優雅。掌握此類位運算規律對解決範圍位運算問題至關重要。