題目:請實現一個函數,輸入一個整數,輸出該數二進制表示中1的個數。例如把9表示成二進制是1001,有2位是1。所以若是輸入9,該函數輸出2。函數
一個基本的思路:先判斷整數二進制表示中最右邊一位是否是1。接着把輸入的整數右移一位,此時原來處於從右邊數起的第二位被移到最右邊了,再判斷是否是1。這樣每次移動一位,直到整個整數變成0爲止。單元測試
怎麼判斷一個整數的最右邊是否是1:只要把整數和1作位與運算看結果是否是0就知道了。測試
public static int NumberOf1Solution1(int n) { int count = 0; while (n > 0) { if ((n & 1) == 1) { count++; } n = n >> 1; } return count; }
PS:右移運算符m>>n表示把m右移n位。右移n位的時候,最右邊的n位將被丟棄。若是數字原先是一個正數,則右移以後在最左邊補n個0;若是數字原先是負數,則右移以後在最左邊補n個1。例以下面對兩個八位二進制數進行右移操做:ui
00001010>>2=00000010spa
10001010>>3=11110001code
那麼,問題來了:上面的方法若是輸入一個負數,好比0x80000000,若是一直作右移運算,最終這個數字就會變成0xFFFFFFFF而陷入死循環。blog
爲了不死循環,咱們能夠不右移輸入的數字i:get
(1)首先把i和1作與運算,判斷i的最低位是否是爲1。博客
(2)接着把1左移一位獲得2,再和i作與運算,就能判斷i的次低位是否是1。it
(3)這樣反覆左移,每次都能判斷i的其中一位是否是1。
public static int NumberOf1Solution2(int n) { int count = 0; uint flag = 1; while (flag >= 1) { if ((n & flag) > 0) { count++; } flag = flag << 1; } return count; }
PS:這個解法中循環的次數等於整數二進制的位數,32位的整數須要循環32次。
把一個整數減去1,再和原整數作與運算,會把該整數最右邊一個1變成0。那麼一個整數的二進制表示中有多少個1,就能夠進行多少次這樣的操做。
public static int NumberOf1Solution3(int n) { int count = 0; while (n > 0) { count++; n = (n - 1) & n; } return count; }
PS:把一個整數減去1以後再和原來的整數作位與運算,獲得的結果至關因而把整數的二進制表示中的最右邊一個1變成0。不少二進制的問題均可以用這個思路解決。
// 輸入0,期待的輸出是0 [TestMethod] public void NumberOfOneInBinaryTest1() { Assert.AreEqual(BinaryHelper.NumberOf1Solution2(0),0); Assert.AreEqual(BinaryHelper.NumberOf1Solution3(0),0); } // 輸入1,期待的輸出是1 [TestMethod] public void NumberOfOneInBinaryTest2() { Assert.AreEqual(BinaryHelper.NumberOf1Solution2(1), 1); Assert.AreEqual(BinaryHelper.NumberOf1Solution3(1), 1); } // 輸入10,期待的輸出是2 [TestMethod] public void NumberOfOneInBinaryTest3() { Assert.AreEqual(BinaryHelper.NumberOf1Solution2(10), 2); Assert.AreEqual(BinaryHelper.NumberOf1Solution3(10), 2); } // 輸入0x7FFFFFFF,期待的輸出是31 [TestMethod] public void NumberOfOneInBinaryTest4() { Assert.AreEqual(BinaryHelper.NumberOf1Solution2(0x7FFFFFFF), 31); Assert.AreEqual(BinaryHelper.NumberOf1Solution3(0x7FFFFFFF), 31); } // 輸入0xFFFFFFFF(負數),期待的輸出是32 [TestMethod] public void NumberOfOneInBinaryTest5() { Assert.AreEqual(BinaryHelper.NumberOf1Solution2(0xFFFFFFFF), 32); Assert.AreEqual(BinaryHelper.NumberOf1Solution3(0xFFFFFFFF), 32); } // 輸入0x80000000(負數),期待的輸出是0 [TestMethod] public void NumberOfOneInBinaryTest6() { Assert.AreEqual(BinaryHelper.NumberOf1Solution2(0x80000000), 0); Assert.AreEqual(BinaryHelper.NumberOf1Solution3(0x80000000), 0); }
(1)測試經過狀況:
(2)代碼覆蓋率: