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.
Hint:
You should make use of what you have produced already.
Divide the numbers in ranges like [2-3], [4-7], [8-15] and so on. And try to generate new range from previous.
Or does the odd/even status of the number help you in calculating the number of 1s?
这道题问的是给出一个数n, 求0到n 的所有数的二进制形式的1的个数。
首先想到的是被题目说很low 的每个数都除以2算余数的方法。
之后第二个反应是 使用函数:buildin 中的bitset(结果题目又说 do it without using any builtin function。。。)
解法一:
class Solution {
public:
vector<int> countBits(int num) {
vector<int> res;
for (int i = 0; i <= num; ++i) {
res.push_back(bitset<32>(i).count());
}
return res;
}
};
解法二:
好吧不用就不用
我们可以发现每个i值都是i&(i-1)对应的值加1,这样我们就可以写出代码:
class Solution {
public:
vector<int> countBits(int num) {
vector<int> res(num + 1, 0);
for (int i = 1; i <= num; ++i) {
res[i] = res[i & (i - 1)] + 1;
}
return res;
}
};
解法三: 这个是ac 之后看到的一种解法
利用的是二进制表示时1出现的次数等于i/2中1出现的次数加1(如果i用二进制表示时最右边一位为1,否则不加1
class Solution {
public:
vector<int> countBits(int num) {
if (num <= 0)
return vector<int>(1, 0);
vector<int> ret(num+1, 0);
int i = 0;
int half = 0;
for (i = 1; i <= num; ++i)
{
//the number of 1's in half equals the number of 1's in i except the right-most bit in i
half = i >> 1;
if (i % 2 == 0)//the right-most bit in i is 0
ret[i] = ret[half];
else//the right-most bit in i is 1
ret[i] = ret[half] + 1;
}
return ret;
}
};