[劍指offer 15] 二進制中1的個數

請實現一個函數,輸入一個整數,輸出該數二進制表示中 1 的個數。例如,把 9 表示成二進制是 1001,有 2 位是 1。所以,若是輸入 9,則該函數輸出 2。編程

測試用例1:ide

[劍指offer 15] 二進制中1的個數

測試用例2:
[劍指offer 15] 二進制中1的個數函數

測試用例3:
[劍指offer 15] 二進制中1的個數測試

首先來分析題目,要統計二進制中1的個數,那麼咱們首先想到的是 要將此數的每一個比特位都要遍歷一遍,而後判斷爲1count++,最後返回count。就寫出以下代碼優化

int hammingWeight(uint32_t n) {
        int count = 0;
        while(n)
        {
            if(n&1)
                count++;

            //此處移位時,若是n爲負數可能會致使死循環
            n >>= 1;
        }
        return count;
    }

上面的代碼在統計無符號數時,結果是正確的,可是,在算負數時,可能會致使死循環。
此處咱們採用的 位運算 來代替 除法運算,由於計算機中除法的效率要比比移位運算要低得多。咱們在實際編程中要儘可能地用移位運算符代替乘除法。
再者咱們來討論一下測試用例爲負數。右移運算符的特色是,右移n位的時候,最右邊的n位將被丟棄。在右移處理最左邊位的情形比較複雜。若是數字是一個無符號值,則用0填補最左邊的n位;若是數字爲有符號數,則用數字的符號位填補最左邊的n位。也就是說,若是數字原先是正數,則右移以後在最左邊補n個0;若是數字原先是負數,則右移以後在最左邊補n個1。 因此負數在進行移位時,最終因爲最高位一直補1致使最終結果陷入死循環。故設計出上述代碼是由問題的,咱們能夠對其進行調整。ui

  • 正確示範1:
int hammingWeight(uint32_t n) {
        int count = 0;
        unsigned int flag = 1;
        while(flag)
        {
            if(n&flag)
                count++;

            flag = flag << 1;
        }
        return count;
    }

爲了不死循環,此處咱們不右移輸入的數字n,而是把n和1 按位與 ,判斷i的最低位是否是爲1,接着把i左移1位,再和n作按位與運算。這樣反覆右移就能計算出n中二進制位1的個數。這種解法唯一的不足之處是不管n中二進制位有多少個1,都要進行32次循環。那麼還能不能在優化一下呢,答案是確定能夠,來看一下最終比較完美的解答:
完美解答:設計

int hammingWeight(uint32_t n) {
        int count = 0;
        while(n)
        {
            ++count;
            n = (n-1)&n;
        }
        return count;
    }

此處將位運算的靈活性體現到了機制,能夠看出代碼設計的很是巧妙精簡。其精髓就在於此句 n = (n-1)&n 。你們能夠本身體會一下此處的妙筆。3d

相關文章
相關標籤/搜索