leetcode:比特位計數

題目來源:力扣

題目描述:

給定一個非負整數 num。對於 0 ≤ i ≤ num 範圍中的每個數字 i ,計算其二進制數中的 1 的數目並將它們作爲數組返回。
================================================
示例 1:
輸入: 2
輸出: [0,1,1]
示例 2:
輸入: 5
輸出: [0,1,1,2,1,2]
=============================================
給出時間複雜度爲O(n*sizeof(integer))的解答非常容易。但你可以在線性時間O(n)內用一趟掃描做到嗎?

審題:

最簡單的方法是檢查每一整數的比特位,計算爲1的個數.此處我們考慮其他時間複雜度更小的方法.
首先觀察連續整數的比特數組,{0, 1, 10, 11, 100, 101, 110, 111},觀察以上序列我們可以發現如下規律,2的比特位中1的個數等於0的比特位中1的個數+1,3的比特位中1的個數等於1的比特位中1的個數+1,4的比特位中1的個數等於0的比特位中1的個數+1,5的比特位中1的個數等於1的比特位中1的個數+1.我們使用S[i]S[i]表示整數i中比特位爲1的個數,則可以推導出如下公式:
S[i]=S[i%2(int)lg2i]+1S[i] = S[i \% 2^{(int)lg_{2}i}]+1,且S[0]=0,S[1]=1S[0] = 0, S[1] = 1.
基於以上最優子結構推導,我們可以使用動態規劃算法自底向上依次計算S[0], S[1], …S[n].

還有另一中更簡潔的方法,在看了此方法後,深感巧妙.所有整數可分爲奇數和偶數兩種,如果一個數是奇數,則其前一個數是偶數,並且該奇數位爲1的個數等於前一偶數位爲1個數加1,因爲相較於前一偶數,除最低位由0變爲1外,其餘位均相同.如果當前數爲偶數,則該偶數中位爲1的個數等於該偶數除以2對應偶數中位爲1的個數,因爲除以2相當於將當前偶數右移一位,由於右移的最低位爲0,因此移位後整數爲1的個數不變.我們可以推導出如下最優子結構:
ifif i&1==1,S[i]=S[i1]+1i\&1==1, S[i] = S[i-1]+1
elseelse S[i]=S[i>>1]S[i] = S[i >> 1]

java算法:

class Solution {
    public int[] countBits(int num) {
        if(num == 0)
            return new int[]{0};

        int[] S = new int[num+1];
        S[0] = 0;
        S[1] = 1;
        for(int i = 2; i <= num; i++){
            int mod = (int)Math.pow(2, (int)(Math.log(i) / Math.log(2)));
            S[i] = S[i % mod] + 1;
        }
        return S;
    }
}

位運算版本

class Solution {

    public int[] countBits(int num) {
        if(num == 0)
            return new int[]{0};

        int[] S = new int[num+1];
        S[0] = 0;
        S[1] = 1;
        for(int i = 2; i <= num; i++)
            if((i & 1) == 0)
                S[i] = S[i >> 1];
            else
                S[i] = S[i-1] + 1;
        return S;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章