題目描述
輸入一個整數,輸出該數二進制表示中1的個數。其中負數用補碼錶示。
這道題有一個公式 n &= (n - 1)
,也就是計算n的二進制表示1的個數,只要循環使用上面的公式,直到n爲0。這個公式不知道就記住即可,下面用個示例簡單驗證一下公式的正確性,不是很嚴謹。
假設 n = +127,則二進制形式爲"0111 1111"(假設長度爲一個字節,最高位爲符號位,0表示正數,1表示負數)
第一次計算,n = +127,n & (n - 1) == "0111 1111" & "0111 1110" == "0111 1110"(十進制爲+126)
第二次計算,n = +126,n & (n - 1) == "0111 1110" & "0111 1101" == "0111 1100"(十進制爲+124)
第三次計算,n = +124,n & (n - 1) == "0111 1100" & "0111 1011" == "0111 1000"(十進制爲+120)
第四次計算,n = +120,n & (n - 1) == "0111 1000" & "0111 0111" == "0111 0000"(十進制爲+112)
第五次計算,n = +112,n & (n - 1) == "0111 0000" & "0110 1111" == "0110 0000"(十進制爲+96)
第六次計算,n = +96, n & (n - 1) == "0110 0000" & "0101 1111" == "0100 0000"(十進制爲+64)
第七次計算,n = +96, n & (n - 1) == "0100 0000" & "0011 1111" == "0000 0000"(十進制爲+0)
第八次計算,n = 0,停止計算
不難發現,每次計算n & (n - 1),都是把n的二進制形式最後一位1置爲0.
當n爲負數的時候,需要用補碼形式計算,而計算機中默認就是補碼(正數的補碼與原碼相同,
負數的補碼是原碼除符號位外各位取反再+1)形式存儲,所以計算過程類似。
(如果原碼、補碼不知道是什麼的話,那就跳過吧。
class Solution {
public:
int NumberOf1(int n) {
int count = 0;
while (n != 0) {
//統計n的二進制形式1的個數
n &= (n - 1);
count += 1;
}
return count;
}
};
題1、LeetCode 搜索插入的位置(二分查找)
題2、LeetCode 搜索旋轉排序數組(二分搜索)
題3、LeetCode 在排序數組中查找元素的第一個和最後一個位置(二分查找)