Leetcode: 338.Counting Bits

Leetcode: 338.Counting Bits

題目講的是:給定一個數字,按順序輸出範圍[0,n]之間的所有整數的二進制表示中1的個數。

粗暴的做法是,歷遍[0,n]。對每一個數字轉化成二進制,然後一位一位地數。這個複雜度是O(n*sizeof(integer))。

題目當然想我們快點啦。希望我們在O(n)複雜度裏面解決。所以是用的DP。找一下規律。我找到的規律是:

        if(i%2)
        {
            dp.push_back(dp[i/2]+1);
        }
        else
        {
            dp.push_back(dp[i/2]);
        }

解釋一下,就是以0-1,2-3,4-7,8-15這樣區間去考慮,發現偶數和/2的一致,奇數等於/2+1。

代碼

這樣就可以寫了:

class Solution {
public:
vector<int> countBits(int num)
{
    vector<int> dp;
    if(num == 0)
    {
        dp.push_back(0);
        return dp;
    }

    dp.push_back(0);
    dp.push_back(1);

    if(num == 1)
        return dp;

    for(int i=2;i<=num;i++)
    {
        if(i%2)
        {
            dp.push_back(dp[i/2]+1);
        }
        else
        {
            dp.push_back(dp[i/2]);
        }
    }
    return dp;
}
};

按位與方法

看到我的方法打敗了85%的朋友,很高興地點開了discuss。結果發現leetcode網友打代碼還是剛,一把梭。都開始比較誰寫得短了……我看了一下,方法有所不同,比我這個深奧一些,總結一下就是: ret[i] = ret[i&(i-1)] + 1;

這個方程比較難理解,稍微寫一下之後,大概整理思路如下:

拿到一個數n,設其表示爲1100。現在希望用dp來解決,即用前面已經算出了的值來得到後面的值。那麼發現dp[1100]應該是dp[1000]+1。只需要去掉一個低位的1就可以了,那麼i&(i-1)這個就可以保證去掉一個低位的1(i>=1 )。所以……就可以了。

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