题目:
Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1‘s in their binary representation and return them as an array.
Example:
For num = 5
you should return [0,1,1,2,1,2]
.
Follow up:
- It is very easy to come up with a solution with run time O(n*sizeof(integer)). But can you do it in linear time O(n) /possibly in a single pass?
- Space complexity should be O(n).
- Can you do it like a boss? Do it without using any builtin function like __builtin_popcount in c++ or in any other language.
题目解答:这个题上来一看,就知道可以一次统计每个整数的1的个数,这个思路特别简单。但是从后续的条件中,可以知道,关键是在时间效率和空间效率上。所以,我们来观察一下,数字中含有1的规律:
数字 ------> 对应二进制 ----------> 含有1的个数
0 ------> 0 ----------> 0
1 ------> 1 ----------> 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
。。。
可以注意到,没变一种颜色,相当于在上面所有颜色的对应位置上增加1。这个对应的规则为对cur_num求余数。cur_num的变化规则为:1,2,4,8,16,32,……翻倍的增长。
代码如下:
class Solution {
public:
vector<int> countBits(int num) {
vector<int> res;
if(num < 0)
return res;
if(num == 0)
{
res.push_back(0);
return res;
}
if(num == 1)
{
res.push_back(0);
res.push_back(1);
return res;
}
res.push_back(0);
res.push_back(1);
int cur_num = 2;
int record = cur_num;
int next_num = cur_num * 2;
for(int i = 2;i <= num;i++)
{
cur_num--;
res.push_back(1 + res[i % record]);
if(cur_num == 0)
{
cur_num = next_num;
next_num = cur_num * 2;
record = cur_num;
}
}
return res;
}
};