题目描述:
给你一个整数 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 <= 105
进阶:
很容易就能实现时间复杂度为 O(n log n) 的解决方案,你可以在线性时间复杂度 O(n) 内用一趟扫描解决此问题吗?
你能不使用任何内置函数解决此问题吗?(如,C++ 中的 __builtin_popcount )
思路:先尝试找规律
数字 | 二进制 | 1的个数 |
---|---|---|
0 | 00 | 0 |
1 | 01 | 1 |
2 | 10 | 1 |
3 | 11 | 2 |
4 | 100 | 1 |
5 | 101 | 2 |
6 | 110 | 2 |
7 | 111 | 3 |
8 | 1000 | 1 |
9 | 1001 | 2 |
10 | 1010 | 2 |
11 | 1011 | 3 |
12 | 1100 | 2 |
13 | 1101 | 3 |
14 | 1110 | 3 |
15 | 1111 | 4 |
16 | 10000 | 1 |
17 | 10001 | 2 |
18 | 10010 | 2 |
19 | 10011 | 3 |
20 | 10100 | 2 |
21 | 10101 | 3 |
22 | 10110 | 3 |
23 | 10111 | 4 |
24 | 11000 | 2 |
25 | 11001 | 3 |
26 | 11010 | 3 |
27 | 11110 | 4 |
按照二进制数字个数分的话可以看到数组是
0,1,1,2
0,1,1,2,1,2,2,3
0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4
0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5
可以看到后一半其实就是前一半+1,并且长度也是上一组的一倍
在n小于3的时候我们可以直接定义res=[0,1,1,2]
n大于3的时候,为了保证答案正确,我们选择牺牲存储空间让数组长度变的长一点,最后取我们需要的长度就行
使用temp数组将我们的数据先+1,在加到res数组的后面,就实现了后一半是前一半+1且长度也是一倍的条件
class Solution(object):
def countBits(self, n):
"""
:type n: int
:rtype: List[int]
"""
res=[0,1,1,2]
if n>3:
while len(res)<n+4:
temp=[i+1 for i in res]#temp=[1,2,2,3]
res+=temp#res=[0,1,1,2,1,2,2,3]
return res[:n+1]