跳至主要內容

338. 比特位计数


338. 比特位计数

🟢   🔖  位运算 动态规划  🔗 力扣open in new window LeetCodeopen in new window

题目

Given an integer n, return an arrayans of lengthn + 1 such that foreachi (0 <= i <= n) , ans[i] is thenumber of1 's in the binary representation of i.

Example 1:

Input: n = 2

Output: [0,1,1]

Explanation:

0 --> 0

1 --> 1

2 --> 10

Example 2:

Input: n = 5

Output: [0,1,1,2,1,2]

Explanation:

0 --> 0

1 --> 1

2 --> 10

3 --> 11

4 --> 100

5 --> 101

Constraints:

  • 0 <= n <= 10^5

Follow up:

  • It is very easy to come up with a solution with a runtime of O(n log n). Can you do it in linear time O(n) and possibly in a single pass?
  • Can you do it without using any built-in function (i.e., like __builtin_popcount in C++)?

题目大意

给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案。

示例 1:

输入: n = 2

输出:[0,1,1]

解释:

0 --> 0

1 --> 1

2 --> 10

示例 2:

输入: n = 5

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

解释:

0 --> 0

1 --> 1

2 --> 10

3 --> 11

4 --> 100

5 --> 101

提示:

  • 0 <= n <= 10^5

进阶:

  • 很容易就能实现时间复杂度为 O(n log n) 的解决方案,你可以在线性时间复杂度 O(n) 内用一趟扫描解决此问题吗?
  • 你能不使用任何内置函数解决此问题吗?(如,C++ 中的 __builtin_popcount

解题思路

思路一:逐位统计(暴力解法)

  • 对于每个数字 i,计算其二进制表示中的 1 的个数。
  • 使用内置函数 toString(2) 将数字转换为二进制,然后用 split('1').length - 1 统计 1 的个数。

复杂度分析

  • 时间复杂度O(n * k),其中 k 是转换为二进制表示的位数。
  • 空间复杂度O(n),用于存储结果数组,处理数字时的临时空间需求为 O(log n)

思路二:动态规划 + 最低有效位

观察规律,对于数字 i

  • 如果 i 是偶数,i 的二进制中 1 的个数与 i / 2 相同,因为最低位是 0
  • 如果 i 是奇数,i 的二进制中 1 的个数比 i - 11,因为最低位是 1

递推公式:

  • result[i] = result[i >> 1] + (i & 1)

复杂度分析

  • 时间复杂度O(n),因为仅需线性遍历 i0n
  • 空间复杂度O(n),用于存储结果数组。

思路三:动态规划 + 最高有效位

观察规律,对于数字 i

如果找到数字 i 所对应的最高有效位(如 2^k),可以将 i 分解为 2^k + x,其中 x 是比 2^k 小的余数。

因此,result[i] = result[i - 2^k] + 1

复杂度分析

  • 时间复杂度O(n),因为仅需线性遍历 i0n
  • 空间复杂度O(n),用于存储结果数组。

代码

逐位统计(暴力解法)
/**
 * @param {number} n
 * @return {number[]}
 */
var countBits = function (n) {
	return new Array(n + 1)
		.fill(0)
		.map((_, i) => i.toString(2).split('1').length - 1);
};

相关题目

题号标题题解标签难度力扣
191位1的个数[✓]位运算 分治🟢🀄️open in new window 🔗open in new window
2859计算 K 置位下标对应元素的和位运算 数组🟢🀄️open in new window 🔗open in new window
2917找出数组中的 K-or 值位运算 数组🟢🀄️open in new window 🔗open in new window