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.
my solution:
大致思路:
刚好是2的n次方开始,就可以利用前面的结果了,如。
0000
0001
0010 (开始利用[0,1]的结果,再加上自身最高位1)
0011
0100 (开始利用[0,3]的结果,再加上自身最高位1)
0101
0110
0111
1000 (开始利用[0,7]的结果,再加上自身最高位1)
....
class Solution {
public:
vector<int> countBits(int num) {
init_arr();
vector<int> temp(num+1,0);
//记录当前访问数据最左边1的位置
int high_bit = 2;
temp[0] = 0;
if (num >=1)
temp[1] = 1;
//全部都是基于前面扩展的
for (int i = 2; i <= num; ++i){
//arr[2]为4,arr[1]为2
if (high_bit < 32 && arr[high_bit] <= i)
++ high_bit;
temp[i] = temp[i - arr[high_bit -1] ] + 1;
}
return temp;
}
static void init_arr(){
if(0!=init_flag)
return;
int value = 1;
arr[0] = value;
for (int i = 1; i < ARR_SIZE; ++i)
{
value = value << 1;
arr[i] = value;
}
init_flag = 1;
}
static const int ARR_SIZE = sizeof(int)*8;
static int arr[ARR_SIZE];
static int init_flag;
};
int Solution::init_flag = 0;
int Solution::arr[ARR_SIZE];
C版本的:
int arr [32] = {1<<0,1<<1,1<<2,1<<3,1<<4,1<<5,1<<6,1<<7,
1<<8,1<<9,1<<10,1<<11,1<<12,1<<13,1<<14,1<<15,
1<<16,1<<17,1<<18,1<<19,1<<20,1<<21,1<<22,1<<23,
1<<24,1<<25,1<<26,1<<27,1<<28,1<<29,1<<30,1<<31};
int* countBits(int num, int* returnSize) {
//记录当前访问数据最左边1的位置
int high_bit = 2;
int* temp = (int*)malloc(sizeof(int)*(num+1));
temp[0] = 0;
*returnSize = num+1;
if (num >=1)
temp[1] = 1;
//全部都是基于之前的扩展的
for (int i = 2; i <= num; ++i){
//arr[2]为4,arr[1]为2
if (high_bit < 32 && arr[high_bit] <= i)
++ high_bit;
temp[i] = temp[i - arr[high_bit -1] ] + 1;
}
return temp;
}