每天一道演算法題:數字二進位形式中1的個數

來源:互聯網
上載者:User

標籤:style   class   blog   code   color   問題   

題目:請實現一個函數,屬於一個整數,輸出該數二進位表示中1的個數,例如把9表示成二進位是1001,有2位為1。因此如果輸入9,該函數輸出2。

  • 可能的死迴圈陷阱

     看完題目,相信大家很快就能想到一個解題思路:先判斷整數二進位表示中最右邊的一位是否為1,接著把輸入的整數右移一位,此時原來處於從右邊起的第二位被移動至最右邊了,再判斷是不是1,這樣每次移動一位,直到這個整數變成0,即能夠得到整數二進位表示形式中1的個數,而現在問題變為如何判斷數位最後一位為1,其實這個也很簡單,只需要將數字與1做與運算,如果結果為1,則表示最後一位為1,否則為0。有了上面的思路,我們很快能寫出如下的代碼:

 1 int NumberOf1(int number) 2 { 3     int count = 0; 4      5     while (0 != number) 6     { 7         if (0 != (number & 0x01)) 8         { 9             ++count;10         }11 12         number = number >> 1;13     }    14 15     return count;16 }

  作為一個嚴謹的程式猿,寫完代碼必須要對代碼進行相應的測試,當我們輸入正整數時,程式能夠正確運行,但是當我們輸入負整數時,程式好像不能停止了,為什麼會這樣?當我們再回頭去看代碼,並看到number = number >> 1時,才恍然大悟,因為負數帶有符號位,而在進行右移操作時,由於要保持其任然為負數,會在左邊的第一位補1而不是0,這樣一直進行以為,最終整數變為了0XFFFFFFFF,而陷入死迴圈。如何避免該問題呢?

  • 常規解法

  當上面的問題出現時,我們想到,既然不能將整數向右移動,那我們為什麼不將1向左邊移位後再與輸入整數進行與運算呢?這樣的處理方式能達到同樣的效果,並且左移永遠都只會在右邊的位置補0,這樣就避免了死迴圈的出現,好了,有了這樣的思路我們又寫出下面的第二個版本代碼:

 1 int NumberOf1(int number) 2 { 3     int count = 0; 4     int flag = 0x01; 5  6     while (0 != flag) 7     { 8         if (0 != (number & flag)) 9         {10             ++count;11         }12 13         flag = flag << 1;14     }15 16     return count;17 }

  當完成代碼之後,進行測試都能得到正確的結果,似乎已經是完美答案了,but,我們發現不管我們輸入的整數二進位形式中有幾個1,我們的程式都將迴圈32次才能得到結果,有沒有什麼方法能夠使我們的迴圈次數更少呢?比如二進位中有幾個1就只迴圈幾次的方法,答案是肯定的,請接著往下看。

  • 驚豔的解法

    再分析演算法之前,我們先來分析把一個整數減1的情況,如果一個整數不等於0,那麼該整數的二進位表示中至少有1位是1,先假設這個數的最後一位是1,將該整數減1之後,最後一位變為0,其他位保持不變,接下來假設最後一位不是1而是0的情況,如果該數最右邊的1位於第m位,則將此數減1之後,該數的第m位由1變為0,而m位之後的所有位都由0變為1,第m位之前的位都保持不變,如果再將該整數與該整數減1之後的結果進行與運算,其效果相當於把整數最右邊為1的位由1變為0。我們把上面的分析總結起來就是:把一個整數減1之後再與整數本身做與運算,會把整數二進位形式中最右邊的一個1變成0,那麼一個整數的二進位形式中存在多少個1,我們就可以對該整數做幾次上述的操作,有了上面的思路,我們能寫出新的解法:

 1 int NumberOf1(int number) 2 { 3     int count = 0; 4  5     while (0 != number) 6     { 7         ++count; 8  9         number = number & (number - 1);10     }11 12     return count;13 }

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.