劍指offer 二進位制中1的個數

2021-09-25 11:22:17 字數 3241 閱讀 4833

題目:

輸入乙個整數,輸出該數二進位制表示中1的個數。其中負數用補碼表示。

解法一:

class

solution

:def

numberof1

(self, n)

:# write code here

sum=

0while n !=0:

if n &1==

1:sum+=

1 n = n >>

1return

sum

上面的**對於正數沒有任何問題,但是對於負數就會出現死迴圈,因為-1右移仍然是-1,而不會變成0,所以迴圈不會終止。有關-1右移一位還是-1的內容請參考:負數的二進位制表示與位運算

解法二:

既然上面的解法存在問題,我們就得使用另一種解法。這種解法是劍指offer上給出的解法。利用二進位制減法的性質,如果乙個二進位制數的最後一位是1,則減去1後最後一位變成0,其他位不變。如果最後一位不為0,則減去1後最右邊的1變成0,右邊的0變成1,前面的位不變。所以n&(n-1)可以消掉最右邊的一位1。迴圈使用這種方法,每次可以消掉乙個1,直到n變成0。

當年我很年輕,不知人生苦短,所以我用c++,下面是c++通過的**:

class solution 

return count;}}

;

使用c++上面的**沒有任何問題,可以順利通過測試。

但是,當我不再年輕,認識到人生苦短之後,我開始使用python,於是我又寫了乙份python**,然而問題來了:

class

solution

:def

numberof1

(self, n)

:# write code here

# n&n-1可以消去最後乙個0

count =

0while n !=0:

count +=

1 n = n &

(n-1

)return count

class

solution

:def

numberof1

(self, n)

:# write code here

# n&n-1可以消去最後乙個0

sum=

0if n <0:

n = n &

0xffffffff

while n !=0:

sum+=

1 n = n &

(n-1

)return

sum

但是對於其中的n = n & 0xffffffff我十分疑惑。n與上 0xffffffff還是它本身,為什麼還要與呢?重要的是這樣的**真的能夠解決超時的問題。欲知後事如何我們請往下看。。。

python中的二進位制

print

(bin(5

))print

(bin(-

5))

可以看到5和-5的二進位制表示分別為:

0b101

-0b101

我們知道python沒有位數的限制,python可以表示無限長的整數,所以其實在python中5的二進位制補碼表示其實這樣的:

0000000...101  #前面有無限個0,第一位可以理解為符號位
-5的二進位制補碼表示其實這樣的:

11111111...011  #前面有無限個1,第一位可以理解為符號位
所以在python中,任何負數的二進位制表示都有無限個1。每次n&(n-1)消去最右邊乙個1,但是永遠消不完。

用了python好像苦短的人生更短了。。。

但是為什麼n & 0xffffffff就可以解決這個問題呢:

0xffffffff相當於32位個1,這樣n & 0xffffffff就取出了-5的補碼表示的後32位,-5補碼表示就變成了:

00000....111111.....011 #無限個0,29個1,第一位可以理解為符號位
由於第一位符號位變了,這樣-5的補碼11111111…011就變成了00000....111111.....011就變成了,這樣1的數目就是有限的了。由於前面是0,可以看出這是乙個正數的補碼,通過**我們可以驗證這個數是4294967291。這個正數4294967291的補碼和-5的補碼具有相同數目的1。所以這是乙個我們統計這個正數中含有的1就好了。

print(-

5)print(-

5&0xffffffff

)

-5

4294967291

所以這也解釋了當n小於0時,這句**的有效性n = n & 0xffffffff

解法三:

其實只要明白了,使用python,開始**不work的原因是因為python對負數補碼的表示有無數個1,問題就容易解決了。發現了問題,問題就解決了一半。還有另一種辦法可以解決這種負數的補碼有無限個1的問題。

```python

class

solution

:def

numberof1

(self, n)

:# write code here

# n&n-1可以消去最後乙個0

count =

0if n <0:

#把符號為變成0,剩下的不變

count +=

1 n = n &

0x7fffffff

while n !=0:

count+=

1 n = n &

(n-1

)return count

其實只要理解了我上面的就是這種方法的道理是一樣的,在此就不做過多的解釋了。

其實這都是python的鍋:人生苦短我用python,我用python人生更苦~

上面的內容都是自己的推測和**驗證,如有問題歡迎批評指正~

劍指Offer 二進位制中1的個數

題目 請實現乙個函式,輸入乙個整數,輸出該數二進位制表示中1的個數。例如把9表示成二進位制是1001,有2位是1。因此如果輸入9,該函式輸出2。1 可能引起死迴圈的解法 先判斷整數二進位制表示中最右邊一位是不是1。接著把輸入的整數右移一位,此時原來處於從右邊數起的第二位被移到最右邊了,再判斷最右邊的...

劍指Offer 二進位制中1的個數

輸入乙個整數,輸出該數二進位制表示中1的個數。其中負數用補碼表示。錯誤解法 public class solution return num 若輸入的數字為負數,因為為補碼表示方式,所以高位一直是1,所以會陷入死迴圈。方法一 從高位開始計算 public class solution return ...

劍指OFFER 二進位制中1的個數

public class solution return count 答案正確 恭喜!您提交的程式通過了所有的測試用例 分析一下 這段小小的 很是巧妙。如果乙個整數不為0,那麼這個整數至少有一位是1。如果我們把這個整數減1,那麼原來處在整數最右邊的1就會變為0,原來在1後面的所有的0都會變成1 如果...