题目:比特位计数

  • 给定一个非负整数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)内用一趟扫描做到吗?
  • 要求算法的空间复杂度为O(n)。
  • 你能进一步完善解法吗?要求在C++或任何其他语言中不使用任何内置函数(如C++中的__builtin_popcount)来执行此操作。

来源:力扣(LeetCode)第338题

链接:https://leetcode-cn.com/problems/counting-bits

分析:

  • 由于偶数的二进制数最后一位是0,所以如果一个偶数做>>1运算那么它的1的个数不变。同理如果一个奇数右移一位,1的个数减1。
  • 因此如果1有1个1,那么2也有1个1,3就有2个1。(正推的话做左移运算),如果2有1个1的话,那么4也是1个1,5就是2个1。
  • 所以有了状态转换公式dp[2*i] = dp[i] dp[2*i+1] = dp[i] + 1

代码:

class Solution {
    public int[] countBits(int num) {
        int[] dp = new int[num + 1];
        for (int i = 0; i <= num / 2; i++) {
            dp[i<<1] = dp[i];
            if ((i<<1) + 1 <= num) dp[(i<<1)+1] = dp[i] + 1;
        }
        return dp;
    }
}

复杂度分析:

  • 时间复杂度:O(n) n 为num / 2
  • 空间复杂度:O(n) n 为num