題意:請實現一個函數,輸入一個整數,輸出該數二進制表示中1 的個數。例如把9 表示成二進制是1001,有2 位是1,因此如果輸入9,該輸出2 。
解法一:flag=1,將整數n與flag做位與,判斷位與結果是否爲1,爲1則計數加一;flag左移一位,再重複前面步驟,直到flag爲0。要循環機器字的位數次。這是常規解法,但不算最優解。
解法二:注意到一個二進制數減一後,該數的第一個非0位會變成0,該非0位的右邊的所有位都由0變成1,左邊的所有位保持不變。然後將減一後的數與減一前的數做位與,這樣就將減一前的數的最右邊的非0位變爲0,其他位保持不變。所以通過這種方式就能統計出一個二進制數中1的位數。代碼如下:
int numberOfOne(int n){
int count;
while(n){
count++;
n=(n-1)&n;
}
return count;
}
技巧:把一個整數減去1 之後再和原來的整數做位與運算, 得到的結果相當於是把整數的二進制表示中的最右邊一個1變成0。
很多二進制的問題都可以用這個思總解決。
擴展:(1)用一條語句判斷一個整數是不是2 的整數次方。一個整數如果是2的整數次方, 那麼它的二進制表示中有且只有一位是1, 而其他所有位都是0 。 根據前面的分析, 把這個整數減去1 之後再和它自己做與運算,這個整數中唯一的1 就會變成0。
(2)輸入兩個整數m 和n ,計算需要改變m 的二進制表示中的多少位才能得到n . 比如10 的二進制表示爲1010 ,13的二進制表示爲1101,需要改變1010 中的3 位才能得到1101 . 我們可以分爲兩步解決這個問題:第一步求這兩個數的異或, 第二步統計異或結果中1的位數。