- Total Accepted: 74486
- Total Submissions: 123045
- Difficulty: Medium
- Contributor: LeetCode
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.
解题思路:
看完题目之后首先想到的是从每个数字的二进制数着手。对所有n≥1,发现去掉最高位(必然为1)之后,都会和一个小于它的数相同,自然它们的1的个数也相同。那么对应的是哪个小于它的数呢?其实,去掉一个k位二进制数的最高位,就等于这个二进制数减去2^(k-1)。因此,用dp[i]记录i的二进制数中的1的个数,可以得到状态转移方程:
1. dp[0] = 0;
2. dp[i] = dp[i-2^(k-1)] + 1, i > 0.
因此可以得到一个时间复杂度和空间复杂度都是O(n)的算法。
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
0000 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 |
1 | 1 | 2 | 2 | 4 | 4 | 4 | 4 | 8 | 8 |
代码:
class Solution {
public:
vector<int> countBits(int num) {
vector<int> res(num + 1, 0);
int power = 1;
for(int i = 1; i <= num; i++){
if(power * 2 == i)
power *= 2;
res[i] = res[i - power] + 1;
}
return res;
}
};