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.
就如提示所说,如果时间复杂度为O(n*sizeof(integer)),则就相当简单了。就是依次判断每个数的二进制表示中1的个数为多少。
int countBitOne(int a){
if(a<0){
return 0;
}
int count=0;
while(a){
int temp=a%2;
count+=temp;
a=a>>1;
}
return count;
}
int* countBits(int num, int* returnSize) {
if(num<0){
return NULL;
}
int *res=(int *)malloc((num+1)*sizeof(int));//注意:要开辟num+1个空间
for(int i=0;i<=num;i++){
res[i]=countBitOne(i);
}
*returnSize=num+1;
return res;
}
原以为按照这种思路来做,不会AC,没想到居然AC了。
思路:
当num<2时结果为:0 1
当num<4时结果为:0 1 1 2
当num<8时结果为: 0 1 1 2 , 1 2 2 3
从上面的结果可以看出,2^i~(2^(i+1))-1区间中数含1的个数为对应的 0~(2^i)-1
的1的个数加1.即
res[pow(2,i)+j]=res[j]+1;0<=j<pow(2,i)且pow(2,i)+j<=num;
实现代码如下:
int mypow(int a,int b){
int res=1;
for(int i=0;i<b;i++){
res*=a;
}
return res;
}
int* countBits(int num, int* returnSize) {
if(num<0){
return NULL;
}
int *res=(int *)malloc((num+1)*sizeof(int));//注意:要开辟num+1个空间
if(res==NULL){
printf("malloc failure");
}
res[0]=0;
*returnSize=num+1;
if(num==0){
return res;
}
res[1]=1;
if(num==1){
return res;
}
//先找到离num最近且大于num的2的幂次
int n=num;
int count=1;
while(n!=1){
n=n>>1;
count++;
}
for(int i=1;i<count;i++){
int powValue=mypow(2,i);
for(int j=0;powValue+j<=num&&j<powValue;j++){//注意: powValue+j<=num
res[powValue+j]=res[j]+1;
}
}
return res;
}