leetcode 位運算(一)

191. 位1的個數

https://leetcode-cn.com/problems/number-of-1-bits/

編寫一個函數,輸入是一個無符號整數,返回其二進制表達式中數字位數爲 ‘1’ 的個數(也被稱爲漢明重量)。

示例 1:輸入:00000000000000000000000000001011,輸出:3
解釋:輸入的二進制串 00000000000000000000000000001011 中,共有三位爲 '1'。
示例 2:輸入:00000000000000000000000010000000,輸出:1
解釋:輸入的二進制串 00000000000000000000000010000000 中,共有一位爲 '1'。
示例 3:輸入:11111111111111111111111111111101,輸出:31
解釋:輸入的二進制串 11111111111111111111111111111101 中,共有 31 位爲 '1'。

思路:
一:python,藉助python的庫函數,bin(將數值轉換成對應的二進制),再轉換成字符串,找出字符串中1的個數。

class Solution(object):
    def hammingWeight(self, n):
        """
        :type n: int
        :rtype: int
        """
        res = 0
        rec = str(bin(n))
        for c in rec:
            if c == "1":
                res += 1
        return res

二:利用n&(n-1),參考http://blog.sina.com.cn/s/blog_8d15072b0102wdfu.html

class Solution(object):
    def hammingWeight(self, n):
        res = 0
        while n > 0:
            n &= (n - 1)
            res += 1
        return res

n&(n-1)的妙用

 下面轉自http://blog.sina.com.cn/s/blog_8d15072b0102wdfu.html

leetcode第191題求一個整數的二進制中1的個數。比如8爲1000,則有1個1,7爲0111,則有3個1.

這題用常規思路很容易解決。但是報出超時的錯誤,百度得到n&(n-1)的妙用:

原理:n與n-1的區別在於,對於n,從右向左數的第一個"1"開始一直到右,和n-1,完全相反。

例如 8 =1000 7 = 0111,可以看出,8的從右向左數第一個1開始,他的左邊和7完全相反。

爲什麼能夠通過n&(n-1)來計算1的個數呢,原理:n&(n-1)是把左邊數第一個1變爲了0,每次都是進行這麼個運算,也就是說沒有必要考慮不是1位,這就實現了跳躍式檢測。 每次用n&=(n-1),都會自動跳過n%1=0的部分(常規求二進制會這麼做)。

弄明白了n&(n-1)的作用,那它有哪些應用?
1. 求某一個數的二進制表示中1的個數

while (n >0 ) {
      count ++;
      n &= (n-1);
}

2. 判斷一個數是否是2的方冪

n > 0 && ((n & (n - 1)) == 0 )

3. 計算N!的質因數2的個數。
容易得出N!質因數2的個數 = [N / 2] + [N / 4] + [N / 8] + ....
下面通過一個簡單的例子來推導一下過程:N = 10101(二進制表示)
現在我們跟蹤最高位的1,不考慮其他位假定爲0,
則在
[N / 2]    01000
[N / 4]    00100
[N / 8]    00010
[N / 8]    00001
則所有相加等於01111 = 10000 - 1
由此推及其他位可得:(10101)!的質因數2的個數爲10000 - 1 + 00100 - 1 + 00001 - 1 = 10101 - 3(二進制表示中1的個數)

推及一般N!的質因數2的個數爲N - (N二進制表示中1的個數)

目前看到只有這些應用,但只要理解了n&(n-1)的原理及作用,在碰到相關問題時也會比較容易解決。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章