題目
請實現一個函數,輸入一個整數,輸出該數二進制表示中 1 的個數。例如,把 9 表示成二進制是 1001,有 2 位是 1。因此,如果輸入 9,則該函數輸出 2。
示例 1:
輸入:00000000000000000000000000001011
輸出:3
解釋:輸入的二進制串 00000000000000000000000000001011 中,共有三位爲 '1'。
示例 2:
輸入:00000000000000000000000010000000
輸出:1
解釋:輸入的二進制串 00000000000000000000000010000000 中,共有一位爲 '1'。
示例 3:
輸入:11111111111111111111111111111101
輸出:31
解釋:輸入的二進制串 11111111111111111111111111111101 中,共有 31 位爲 '1'。
解題思路
解法一:逐位判斷
首先把1和n做位運算,判斷n的最低位是不是1。接着把1左移一位變成2,和n做位運算,判斷n的次低位是不是1。這樣反覆左移,逐位判斷n的每一位是不是1。
複雜度分析:
時間複雜度:O(M),M表示整數二進制的位數,因爲循環次數等於整數二進制的位數,例如32位整數需要循環32次。
空間複雜度:O(1)。
解法二:巧用 n&(n−1)
1)假設一個整數的最右邊一位爲1,減去1之後,最後一位變成0,其他所有位保持不變。
2)假設最後一位不是1而是0,如該整數的二進制表示中最右邊的1位於第m位,那麼減去1之後,第m位由1變成0,第m位之後的所有0變成1,第m位之前的所有數保持不變。
以上兩種情況,歸納起來就是把一個整數減去1,都是把最右邊的1變成0。如果它的右邊還有0,則把所有的0變成1,而它左邊的所有數保持不變。接下來,將這個整數減去1之後的結果,再和原來的整數做位運算,得到的結果相當於把整數的二進制表示中最右邊的1變成0,一個整數的二進制表示中有多少個1就進行幾次這樣的操作。
複雜度分析:
時間複雜度:O(M),設 M 爲二進制數字 n 中 1 的個數,則需循環 M 次(每輪消去一個 1 ),佔用 O(M)。
空間複雜度:O(1)。
代碼
解法一:逐位判斷
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int count = 0;
int flag = 1;
while(flag!=0){
if((n & flag)!=0){
count++;
}
flag <<= 1;
}
return count;
}
}
解法二:巧用 n&(n−1)
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int count = 0;
while(n!=0){
n = n & (n-1);
count++;
}
return count;
}
}