問題:
輸入一個整數,輸出該數二進制表示中1的個數。其中負數用補碼錶示。
解題思路:
因爲負數用補碼錶示,對於負數右移時,在最高位補得是1,因此負數移位位產生無限個1,陷入死循環。
出現死循環的錯誤答案:
int NumberOf1_CanNotUse(int n) {
int count = 0;
while (n != 0) {
// 用1和n進行位與運算,結果要是爲1則n的2進制形式最右邊那位肯定是1,否則爲0
if ((n & 1) == 1) {
count++;
}
//把n的2進制形式往右推一位
n = n >> 1; //負數右移,首位補一,導致無數個1
}
return count;
}
答案1:解決負數死循環問題
思想:當n爲負數的時候,可以將最高位的符號位1變成0,就是n & 0x7FFFFFFF,這樣就把負數轉化成正數了,唯一差別就是最高位由1變成0,因爲少了一個1,所以count加1。之後再按照while循環裏處理正數的方法來操作就可以啦!
int NumberOf1(int n) {
int count = 0;
if(n < 0){
n = n & 0x7FFFFFFF;
++count;
}
while(n != 0){
count += n & 1;
n = n >> 1;
}
return count;
}
答案2:用1左移
思想:用1(1自身左移運算,其實後來就不是1了)和n的每位進行位與,來判斷1的個數
int NumberOf1_low(int n) {
int count = 0;
int flag = 1;
while (flag != 0) { // 直到1左移超出int範圍變爲0,要循環32次。
if ((n & flag) != 0) {
count++;
}
flag = flag << 1;
}
return count;
}
答案3:最優解:用(n - 1) & n
int NumberOf1(int n) {
int count = 0;
while (n != 0) {
++count;
n = (n - 1) & n;
}
return count;
}
引用:
1、題目來源於牛客網:二進制中1的個數
2、答案與解題思路來源於:AlenZhang與writezen
總結:
1、善於利用以爲運算符和按位與&。