338 比特位计数

少于 1 分钟阅读

标签: ,

题目

题目链接:338 比特位计数

给定一个非负整数 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)来执行此操作。

思路

  1. 主要思路:找规律(动态规划的状态转移)
    1. $偶数$ 的 1 的个数 = $\frac{该偶数}{2}$ 的 1 的个数
    2. $奇数$ 的 1 的个数 = 「$该奇数 - 1$ 的 1 的个数」+ 1
  2. 🌰:
    1. 20
      1. $20$ 的二进制:10100, 1 的个数为 2;
      2. $\frac{20}{2} = 10$ 的二进制:1010,1 的个数为 2;
      3. 规律:$20$ 是在 $10$ 的基础上 乘 2
      4. 在位运算中的表现为:$10$ 左移一位得到 $20$,因此 1 的个数的相同的。
    2. 27
      1. $27$ 的二进制:11011, 1 的个数为 4;
      2. $26$ 的二进制:11010, 1 的个数为 3;
      3. 规律:$27$ 是在 $26$ 的基础上 加 1
      4. 在位运算中的表现为:$27$ 的二进制中 1 的个数比$26$ 的二进制中 1 的个数多 1 个。

代码

class Solution:
    def countBits(self, num: int) -> List[int]:
        res = [0] * (num+1)
        for i in range(num+1):
            if i % 2 == 0:
                res[i] = res[i//2]
            else:
                res[i] = res[i-1] + 1
        return res

分析

  1. 时间复杂度需要 O(n),一次线性遍历即可;
  2. 空间复杂度需要 O(n),保存结果。

留下评论