1.题目描述
给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回。
示例 1:
输入: 2
输出: [0,1,1]
示例 2:
输入: 5
输出: [0,1,1,2,1,2]
2.题目分析
问题要求返回0~num二进制数中1的个数,先写几个二进制数看看规律
十进制数 | 二进制数 | 1的个数 |
---|---|---|
0 | 0000 | 0 |
1 | 0001 | 1 |
2 | 0010 | 1 |
3 | 0011 | 2 |
4 | 0100 | 1 |
5 | 0101 | 2 |
6 | 0110 | 2 |
7 | 0111 | 3 |
观察上表,可以看出以下几个结论:
-
2的整数次幂1的个数是1(首位是1,后面全0)
-
有递推的关系(以7为例):
观察1、3、7的二进制表示十进制数 二进制数 1的个数 1 0001 1 3 0011 2 7 0111 3 0111就是0011多一个高位,同样的0011是0001多一个高位
f ( x ) 表 示 x 的 二 进 制 表 示 中 1 的 个 数 f ( 7 ) = f ( 3 ) + 1 f ( 3 ) = f ( 1 ) + 1 f(x)表示x的二进制表示中1的个数\\ f(7)=f(3)+1\\ f(3)=f(1)+1\\ f(x)表示x的二进制表示中1的个数f(7)=f(3)+1f(3)=f(1)+1
按照这个思路很自然想到递归求个数,反过来就是动态规划了。套用上面的规律可以得到:
f
(
x
)
=
f
(
x
−
y
)
+
1
y
是
小
于
x
的
最
大
的
2
的
幂
次
方
在
上
例
中
7
对
应
4
,
3
对
应
1
f(x)=f(x-y)+1\\y是小于x的最大的2的幂次方\\在上例中7对应4,3对应1
f(x)=f(x−y)+1y是小于x的最大的2的幂次方在上例中7对应4,3对应1
得到递推方程后即可写出代码:
class Solution {
public int[] countBits(int num) {
int[] binNum = new int[num+1];
binNum[0] = 0;
if(num == 0){
return binNum;
}
binNum[1] = 1;
int temp1 = 2;
int temp2 = 2 * temp1;
for (int i = 2; i <= num; i++) {
if(i == temp2){
binNum[i] = 1;
temp1 = temp2;
temp2 *= 2;
}
binNum[i] = binNum[i-temp1] + 1;
}
return binNum;
}
}
这里用了temp中间变量来寻找2的整数次幂,在官方题解里找到一个简单方法(注意到这种数最高位1低位全0):
y&(y−1)=0 //y是2的整数次幂
2021-3-3打卡成功!继续加油!