20210303 LeetCode 每日一题,冲!|刷题打卡

283 阅读2分钟

题目描述

Leetcode 链接:338. 比特位计数(medium)

给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回。

示例:

输入: 2
输出: [0,1,1]

输入: 5
输出: [0,1,1,2,1,2]

提示:

  • 给出时间复杂度为 O(n*sizeof(integer)) 的解答非常容易。但你可以在线性时间 O(n )内用一趟扫描做到吗?
  • 要求算法的空间复杂度为O(n)。
  • 你能进一步完善解法吗?要求在C++或任何其他语言中不使用任何内置函数(如 C++ 中的 __builtin_popcount)来执行此操作。

JavaScript 模板:

/**
 * @param {number} num
 * @return {number[]}
 */
var countBits = function(num) {

};

思路分析

这道题的题目还是比较清楚的,基本上一看就能知道题目在问什么。看到之后的第一个思路便是采用位运算,对小于 num 的每一个整数进行一次运算,判断其拥有多少个 1:

  1. 判断有多少个 1 的函数:
countOnes = (x) => {
  let ones = 0;
  while (x > 0) {
    (x & 1) && ones++; 
    x >>= 1;
  }
  return ones;
}
  1. 从 0 遍历到 num,为每一个整数调用一次上面的函数,然后结合一下:
var countBits = function (num) {
  const bits = new Array(num + 1).fill(0),
    countOnes = (x) => {
      let ones = 0;
      while (x > 0) {
        (x & 1) && ones++;
        x >>= 1;
      }
      return ones;
    };
  for (let i = 0; i < num + 1; i++) {
    bits[i] = countOnes(i);
  }
  return bits;
};

时间复杂度为 O(n2), 空间复杂度为 O(1)

总结一下

本 dp 渣虽然能一眼看出这是一道 dp 题,奈何本渣渣就是不知道做。看着官方题解里三种 dp 的解法,我居然一种都看不懂,不禁流下眼泪。希望 3 月不要是 dp 月,让我安心上上课 (ง •_•)ง

顺便问一下有没有 dp 大佬给我理理思路?

小伙伴们一起来用 JavaScript 刷算法吧:LeetCode-JavaScript

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情