題目描述:給定兩個整數 left 和 right(其中 left <= right),返回 [left, right] 範圍內所有整數做 AND 運算的結果。
解題思路:
暴力枚舉所有數字逐一做 AND 在 right - left 很大時會超時。關鍵觀察是:AND 結果等於 left 和 right 的二進位公共前綴。
為什麼? 考慮 left 和 right 的二進位表示。若它們在某個位元上不同,代表在 [left, right] 這段範圍內,必然存在某個數字使得該位元為 0(因為從 left 計數到 right 時,較低位元會經歷 0 和 1 的所有組合)。因此,所有不屬於公共前綴的位元,在整個範圍的 AND 中都會變為 0。
演算法:同時右移 left 和 right,直到兩者相等(此時我們找到了公共前綴)。記錄移動的次數 shift,最後將相等的值左移 shift 位即為答案。
例如:left = 5 (101), right = 7 (111)
left = 2 (10), right = 3 (11) → 不等left = 1 (1), right = 1 (1) → 相等!1 << 2 = 4 (100),即 5 & 6 & 7 = 4 ✓時間複雜度:O(log n) — 迴圈最多執行 32 次(32 位元整數的位元數),更精確地說是 O(log(max(left, right)))。每次迭代將問題規模減半。
空間複雜度:O(1) — 只使用了常數個額外變數(shift),與輸入大小無關。
1. Initialize shift = 0 2. While left != right: a. Right-shift both: left >>= 1, right >>= 1 b. Increment shift counter: shift++ 3. Return left << shift (restore common prefix to original bit position)
Brian Kernighan 位元清除法 O(log n):重複清除 right 的最低有效位(right = right & (right - 1)),直到 right <= left。此時 right 即為答案。直覺是:right & (right - 1) 每次清除最低位的 1,這等效於將 AND 結果中不屬於公共前綴的位元逐一清零,方向與右移法相反但結果相同。
遮罩累積法 O(log n):維護一個遮罩 mask,每次右移時累積公共前綴的遮罩位元。最終將 left & mask(或 right & mask)作為答案。此方法在概念上更明確地表達「保留公共前綴、清除其他位元」的語意,但程式碼略顯繁瑣。在競賽中,右移法因其簡潔性最為常用。
[left, right] 範圍內所有整數的 OR 結果,解法會如何變化?是否存在類似的位元觀察?