(LeetCodeHot100)338. 比特位计数——counting-bits
(LeetCodeHot100)338. 比特位计数——counting-bits
zhangzhang338. 比特位计数counting-bits
给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案。
示例 1:
1 | 输入:n = 2 |
示例 2:
1 | 输入:n = 5 |
提示:
0 <= n <= 105
- 此题没有见过,直接学习
- (有相应的内置函数用于计算给定的整数的二进制表示中的 1 的数目,例如Integer.bitCount)
要解决这个问题,我们需要计算从 0 到 n 的每个整数的二进制表示中 1 的个数,并返回一个包含这些计数的数组。可以利用动态规划结合二进制数的特性高效求解,避免对每个数单独计算(时间复杂度可优化到 O(n))。
核心思路:利用二进制数的奇偶性和右移特性
>>是右移位运算符,作用是将一个数的二进制表示向右移动指定的位数,并返回移动后的结果(以十进制形式呈现)
观察二进制数的规律:
- 若一个数
i是偶数,则i的二进制表示和i/2的二进制表示完全相同(只是末尾多了一个0),因此1的个数也相同(例如4(100)和2(10)都只有 1 个1)。 - 若一个数
i是奇数,则i的二进制表示比i-1(偶数)多一个1(末尾的0变成1),因此1的个数是i-1的计数加1(例如5(101)比4(100)多一个1,计数为1+1=2)。
结合右移操作(i >> 1 等价于 i/2),可以推导出递推公式:
- 当
i为偶数:count[i] = count[i >> 1] - 当
i为奇数:count[i] = count[i >> 1] + 1
简化后可统一为:count[i] = count[i >> 1] + (i & 1)(i & 1 用于判断奇偶,奇数为 1,偶数为 0)。
代码实现
- 当你用
new int[n + 1]创建数组时,Java 会自动为数组中的每个元素分配默认值:- 整数类型(
int)的默认值是0; - 布尔类型默认
false,引用类型默认null等。
- 整数类型(
1 | class Solution { |
逻辑验证(以 n=5 为例)
i=0:初始化为0(二进制0有 0 个1)。i=1:1 >> 1 = 0,1 & 1 = 1→ans[1] = ans[0] + 1 = 0 + 1 = 1。i=2:2 >> 1 = 1,2 & 1 = 0→ans[2] = ans[1] + 0 = 1 + 0 = 1。i=3:3 >> 1 = 1,3 & 1 = 1→ans[3] = ans[1] + 1 = 1 + 1 = 2。i=4:4 >> 1 = 2,4 & 1 = 0→ans[4] = ans[2] + 0 = 1 + 0 = 1。i=5:5 >> 1 = 2,5 & 1 = 1→ans[5] = ans[2] + 1 = 1 + 1 = 2。
最终结果为 [0,1,1,2,1,2],与示例一致。
复杂度分析
- 时间复杂度:
O(n),只需遍历一次0~n。 - 空间复杂度:
O(n),需要一个长度为n+1的数组存储结果。


