數字範圍按位與
阿新 • • 發佈:2020-12-15
給定範圍 [m, n],其中 0 <= m <= n <= 2147483647,返回此範圍內所有數字的按位與(包含 m, n 兩端點)。
示例 1:
輸入: [5,7]
輸出: 4
示例 2:
輸入: [0,1]
輸出: 0
解題思路:統計兩個數二進位制表示的公共字首
因為假設兩個數在第i位前面都相同,第i位一個為0,一個為1,那麼這兩個數之間一定存在一個數,這個數的第i位為1,且後面的都是0。這樣 ‘按位與’ 之後i位以及之後就都是零了。
所以求兩個數的公共字首即可。
通過兩個數不斷右移,直到兩個數相等。
再左移對應的位數
public int rangeBitwiseAnd(int m, int n) {
int i = 0;
while (m != n){
m >>= 1;
n >>= 1;
i ++;
}
return m << i;
}
補充:最直觀的解決方案就是迭代範圍內的每個數字,依次執行按位與運算,得到最終的結果,但此方法在 [m,n] 範圍較大的測試用例中會因超出時間限制而無法通過。
迭代範圍內的所有數會導致超時:
public int rangeBitwiseAnd(int m, int n) {
int result = m;
while (m < n)
result &= m++ + 1;
return result;
}
但注意到,當按位與的結果為0時,後面的數再執行,結果也都為0.所以當按位與的結果為0時就可以終止迴圈:
public int rangeBitwiseAnd(int m, int n) {
int result = m;
while (m < n && result != 0)
result &= m++ + 1;
return result;
}
如此用時604毫秒,並未超時。