二進位制 二進位制中1的個數

2021-10-14 19:48:21 字數 4155 閱讀 2283

題目:請實現乙個函式,輸入乙個整數,輸出該數二進位制表示中 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)

意為將i32位分成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時,再往右移...