問題描述:
給定範圍 [m, n],其中 0 <= m <= n <= 2147483647,返回此範圍內所有數字的按位與(包含 m, n 兩端點)。
示例 1:
輸入: [5,7]
輸出: 4
示例 2:
輸入: [0,1]
輸出: 0
解題思路:
首先使用暴力解法
class Solution {
public:
int rangeBitwiseAnd(int m, int n) {
int res=m;
for(int i=m;i<=n;i++){
res = res&i;
}
return res;
}
};
超時
下面開始採用另外一種解法
當一個數+1時,總會有這麼一個規律“某一位後的數字,全部被置爲相反數”。舉個例子:
010111 + 1 = 011000,則010111 & 011000 = 010000。那麼,x & (x+1) 後幾位相反數的“與操作”,結果總爲0。
比如5,6,7
5:101
6:110
7:111
從m依次&到n,這樣的話我們只用求出m和n的右邊公共部分,
5&6&7=100,實際上只用5和7的右邊公共部留下了其餘部分全部爲0
class Solution {
public:
int rangeBitwiseAnd(int m, int n) {
int offset=0;
while(m!=n){
m>>=1;
n>>=1;
offset++;
}
return n<<offset;
}
};
這裏是我們依次右移m和n,求出公共前綴,當跳出循環的時候,m=n,在5,6,7的例子中最後m=n=1;
offset是統計右移的位數。最後將n或者m左移即可。