LeetCode Daily challenge - Counting Bits

題目大意

給一個整數n,計算0~n每個數的二進制表示中1出現的次數。

輸入

整數n,輸出一個列表。例如輸入5,輸出[0,1,1,2,1,2],分別表示0,1,2,3,4,5每個數的二進制表示中1出現的次數。

要求: 時間、空間複雜度都爲O(n)

思路

二進制相關題目中有一個經常用到的一個技巧,x & -x,表示x的二進制表示中最後一個1出現的位置往後組成的數。例如x=11011100,那麼x & -x = 100。那麼x - (x & -x)剛好比x的二進制表示少一個1。所以對於數x,可以確定x二進制表示中1出現的次數times[x] = times[x - (x & -x)] + 1

不難想到對於奇數x來說,它的二進制表示中1出現的次數等於x-1中1的次數再加1,即times[x] = times[x - 1] + 1。當然也可以按照上面的方法計算,實際上是一樣的: x - (x & -x) = x - 1, (x % 2 == 1)

由此,可以使用遞推的方式,對奇偶數討論,若x爲

  • 奇數,則times[x] = times[x - 1] + 1
  • 偶數,則times[x] = times[x - (x & -x)] + 1

代碼

class Solution {
public:
    vector<int> countBits(int num) {
        if (num == 0) return {0};
        if (num == 1) return {0, 1};
        vector<int> dp(num + 1, 0);
        dp[0] = 0, dp[1] = 1;
        for (int i = 2; i <= num; i++) {
            if (i & 1) {
                // odd
                dp[i] = 1 + dp[i - 1];
            } else {
                // even
                dp[i] = dp[i - (i & -i)] + 1;
            }
        }
        return dp;
    }
};

總結

利用(x & -x)尋找遞推關係。

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