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.
public class Counting_Bits_338 {
public int[] countBits(int num) {
int[] a = new int[32];
int pointer = 0;
int[] result = new int[num + 1];
int count = 0;
for (int i = 1; i <= num; i++) {
if (a[pointer] == 0) {
a[pointer] = 1;
count++;
} else {
while(a[pointer]==1){
pointer++;
}
a[pointer] = 1;
count++;
pointer--;
while(pointer>=0){
a[pointer] = 0;
count--;
pointer--;
}
pointer = 0;
}
result[i] = count;
}
return result;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Counting_Bits_338 c = new Counting_Bits_338();
System.out.println(Arrays.toString(c.countBits(7)));
}
}
大神的方法,大神发现了规律: f[i] = f[i / 2] + i % 2.public int[] countBits(int num) {
int[] f = new int[num + 1];
for (int i=1; i<=num; i++) f[i] = f[i >> 1] + (i & 1);
return f;
}
三行解决真是太漂亮了,数学拯救人类!
还有其他的规律:
This uses the hint from the description about using ranges. Basically, the numbers in one range are equal to 1 plus all of the numbers in the ranges before it. If you write out the binary numbers, you can see that numbers 8-15 have the same pattern as 0-7
but with a 1 at the front.
My logic was to copy the previous values (starting at 0) until a power of 2 was hit (new range), at which point we just reset the t pointer back to 0 to begin the new range.
这样一看真的:[2,3]是[0,1]对应数字+1;[4,5,6,7]是[0,1,2,3]对应数字+1;[8,9,10,....,15]是[0,1,2,...,7]对应数字+1;我图片中的算法对于每个数字还要算出它的count(小于等于它的最大2指数),时间复杂度也不好,大神给出了两个指针一次遍历的算法:
public int[] countBits(int num) {
int[] ret = new int[num+1];
ret[0] = 0;
int pow = 1;
for(int i = 1, t = 0; i <= num; i++, t++) {
if(i == pow) {
pow *= 2;
t = 0;
}
ret[i] = ret[t] + 1;
}
return ret;
}