題目:請實現乙個函式,輸入乙個整數,輸出該數二進位制表示中 1 的個數。例如,把 9 表示成二進位制是 1001,有 2 位是 1。因此,如果輸入 9,則該函式輸出 2。
示例 1:
輸入:00000000000000000000000000001011
輸出:3
解釋:輸入的二進位制串 00000000000000000000000000001011 中,共有三位為 '1'。
示例 2:
輸入:00000000000000000000000010000000
輸出:1
解釋:輸入的二進位制串 00000000000000000000000010000000 中,共有一位為 '1'。
示例 3:
輸入:11111111111111111111111111111101
輸出:31
解釋:輸入的二進位制串 11111111111111111111111111111101 中,共有 31 位為 '1'。
題解:
本題主要考察的是位運算操作,作為乙個搬磚的碼農,解法較為普通,**如下:
public int hammingweight(int n)
int bit = 1;
int count = 0;
//從n的低位到高位,通過迴圈,bit每次左移1位,即可將n的每位與 1 做一次&運算
while(n!= bit)
//每次迴圈將n該位置0,以便判斷終止條件
n &= bit^(-1);
//bit左移
bit<<=1;
}return count+1;
}
這個解法的效率也不是很低,在leetcode上耗時也能擊敗99.5%的使用者。然而在jdk原始碼中也有乙個獲取二進位制1的個數的方法,看到這種解法後,不得不感嘆大佬們在演算法上的造詣。
原始碼奉上:
public static int bitcount(int i)
簡簡單單的6行**-----------當然,只是步驟簡單,理解起來並不是那麼的容易啊?幾行**,看了我幾個小時,才能懂整個過程的來龍去脈。下面談談我對這些**的理解。
本題以int型為例(long、short、byte等型別解法大同小異),int型32位,也就是二進位制中1的個數最多位32個(100000)佔6位。
**中的二進位制表示:
0x55555555:0101 0101 0101 0101 0101 0101 0101 0101
0x33333333:0011 0011 0011 0011 0011 0011 0011 0011
0x0f0f0f0f:0000 1111 0000 1111 0000 1111 0000 1111
0x3f: 0000 0000 0000 0000 0000 0000 0011 1111
>>>:無符號右移,以0補位
第1行**:
i = i - ((i >>> 1) & 0x55555555)
意為將i的32位分成16組。通過將引數i右移1位,與0x55555555 作&運算,使右移後的奇數字置零,記為i2。再將原i的值減去i2,得到結果:每組值為每組1的個數(每組2位)。
以i=1111 1111 1111 1111 1111 1111 1111 1111(32位1)為例:
經過第1行**運算後,16組每組1個數都為2個。
第2行**:
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
第2行**與1行類似,將32位分成8組,每組4位,計算結果為每4位一組的1的個數。
當前 i的值為:i= 1010 1010 1010 1010 1010 1010 1010 1010;
通過i & 0x33333333求得每組低2位 1的個數,(i >>> 2) & 0x33333333求得每組高2位1的個數,然後相加重新賦值,結果為每4位1的個數。
第3行**:
i = (i + (i >>> 4)) & 0x0f0f0f0f;
將32位分成4組,每組8位,計算結果為每8位一組的1的個數。
當前 i的值為:i=0100 0100 0100 0100 0100 0100 0100 0100;
i + (i >>> 4)計算每組高4位和低4位1的各種之和,並將高4位置零,然後重新賦值。
第4行**:
i = i + (i >>> 8);
將32位分成2組,每組16位,計算結果為每16位一組的1的個數。
當前 i的值為:i=0000 1000 0000 1000 0000 1000 0000 1000;
i + (i >>>8)計算每組高8位和低8位1的各種之和,然後重新賦值。
第5行**:
i = i + (i >>> 16);
當前 i的值為:i=0000 0000 0001 0000 0000 0000 0001 0000;
i + (i >>>16)計算每組高16位和低16位1的各種之和,然後重新賦值。
第6行**:
return i & 0x3f;
i & 0x3f的值為擷取i低6位的值,將高26位置零。由於int型1的個數最多32個,即最多6位可表示。因此低6位的值即為i的1的個數,將其返回,求得結果。
最後,其他整型(long、short 、byte)的解法和int的解放非常相似,可以通過類似方法求解。
二進位制 二進位制起源
現代通訊技術的基礎是二進位制編碼。早在1865年麥克斯韋總結出麥克斯韋方程組之前,美國人摩斯 morse 於1837年發明了摩斯電碼和有線電報。有線電報的出現,具有劃時代的意義 它讓人類獲得了一種全新的資訊傳遞方式,這種方式 看不見 摸不著 聽不到 完全不同於以往的信件 旗語 號角 烽火,這也是二進...
二進位制中1的個數 二進位制中0的個數
1 題目 實現乙個函式,輸入乙個整數,輸出該數二進位制表示中1的個數,例如把9表示成二進位制是1001,有2位是1。因此如果輸入9,該函式輸出2。2 解法 解法 一 可能會引起死迴圈的解法 基本思路 先判斷整數二進位制表示中最右邊一位是不是1。接著把輸入的整數右移一位,此時原理處於從右邊數起的第二位...
二進位制1的個數
輸入乙個整數,輸出該數二進位制表示中1的個數。其中負數用補碼表示。可能引起死迴圈的解法 class solution return cnt 由於數字在計算機中的二進位制儲存事實上並不包含符號 也就是 都是統一用補碼表示的。移位操作會保證數的正負不變,當遇到乙個負數,右移到最前面的符號位1時,再往右移...