位1的個數系列(一)

想了解更多數據結構以及算法題,可以關注微信公衆號“數據結構和算法”,每天一題爲你精彩解答。也可以掃描下面的二維碼關注
在這裏插入圖片描述
我們知道在java語言中一個int類型有32個0或1組成。我們要計算有多少個1,這裏主要以int型數據爲例來分析。比如15在二進制中表示的是1111,有4個1,所以返回4。再比如16在二進制中表示的是10000,只有一個1,所以返回1。這題解法比較多,我們將會逐個分析。

一,通過移動數字計算

首先想到的是把要求的數字不停的往右移,然後再和1進行與運算,我們就以13爲例畫個圖來分析下

在這裏插入圖片描述
看明白了上面的分析,代碼就很容易多了,我們來看下代碼

public int bitCount(int n) {
    int count = 0;
    for (int i = 0; i < 32; i++) {
        if (((n >>> i) & 1) == 1) {
            count++;
        }
    }
    return count;
}

上面的分析中我們看到,如果一個數往右移了幾步之後結果爲0了,就沒必要在計算了,所以代碼我們還可以在優化一點

public int bitCount(int n) {
    int count = 0;
    while (n != 0) {
        count += n & 1;
        n = n >>> 1;
    }
    return count;
}

二,通過移動1來計算

上面我們使用的是把一個數字不斷的往右移動,其實我們還可以保持原數字不變,用1和他進行與運算,然後通過移動1的位置來計算,這裏我們判斷的標準不是等於1,而是不等於0。我們還以13爲例來畫個圖分析一下

在這裏插入圖片描述
這次我們移動的是1,我們來看一下代碼

public int bitCount(int n) {
    int count = 0;
    for (int i = 0; i < 32; i++) {
        if ((n & (1 << i)) != 0) {
            count++;
        }
    }
    return count;
}

當然我們還可以通過運算的結果是否是1來判斷也是可以的,我們只需要把往左移的1和n運算完之後再往右移即可,我們來看下代碼

public int bitCount(int i) {
    int count = 0;
    for (int j = 0; j < 32; j++) {
        if ((i & (1 << j)) >>> j == 1)
            count++;
    }
    return count;
}

三,不通過移位計算

前面兩種方式要麼是移動原數字,要麼是移動1,這次我們不移動任何數字來計算。在位運算中有這樣一個操作,就是n&(n-1)可以把n最右邊的1給消掉。舉個例子,當n=12的時候,我們來畫個圖看一下
在這裏插入圖片描述
明白了這個知識點,代碼就很容易寫了,我們通過循環計算,不斷的把n右邊的1給一個個消掉,直到n等於0爲止

public int bitCount(int n) {
    int count = 0;
    while (n != 0) {
        n &= n - 1;
        count++;
    }
    return count;
}

我們還可以把它給爲遞歸的寫法,直接一行代碼搞定

public int bitCount(int n) {
    return n == 0 ? 0 : 1 + bitCount(n & (n - 1));
}

四,查表

我們還可以通過查表來計算,我們先要把0到15轉化爲二進制,記錄下每個數字包含1的個數再構成一張表,然後再把數字n每4位進行一次計算,圖就不畫了,代碼中有註釋,我們來看下代碼

 public int bitCount(int i) {
     //table是0到15轉化爲二進制時1的個數
     int table[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
     int count = 0;
     while (i != 0) {//通過每4位計算一次,求出包含1的個數
         count += table[i & 0xf];
         i >>>= 4;
     }
     return count;
}

這題我感覺還是比較經典的,因爲他的解法非常多,上面的幾種要麼使用循環,要麼使用遞歸,要麼是查表,其實我們還可以上面幾種方式都不使用,也可以計算1的個數,這個後面會再講。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章