Write an algorithm to find F(n)
the number of bits set to 1, in all numbers from 1 to n for any given value of n.
Complexity should be O(log n)
The way to solve these sorts of problems is to write out the first few values, and look for a pattern
Number binary # bits set F(n) 1 0001 1 1 2 0010 1 2 3 0011 2 4 4 0100 1 5 5 0101 2 7 6 0110 2 9 7 0111 3 12 8 1000 1 13 9 1001 2 15 10 1010 2 17 11 1011 3 20 12 1100 2 22 13 1101 3 25 14 1110 3 28 15 1111 4 32
It takes a bit of staring at, but with some thought you notice that the binary-representations of the first 8 and the last 8 numbers are exactly the same, except the first 8 have a 0
in the MSB (most significant bit), while the last 8 have a 1
. Thus, for example to calculate F(12)
, we can just take F(7)
and add to it the number of set bits in 8, 9, 10, 11 and 12. But that's the same as the number of set-bits in 0, 1, 2, 3, and 4 (ie. F(4)
), plus one more for each number!
# binary 0 0 000 1 0 001 2 0 010 3 0 011 4 0 100 5 0 101 6 0 110 7 0 111 8 1 000 <--Notice that rightmost-bits repeat themselves 9 1 001 except now we have an extra '1' in every number! 10 1 010 11 1 011 12 1 100
Thus, for 8 <= n <= 15
, F(n) = F(7) + F(n-8) + (n-7)
. Similarly, we could note that for 4 <= n <= 7
, F(n) = F(3) + F(n-4) + (n-3)
; and for 2 <= n <= 3
, F(n) = F(1) + F(n-2) + (n-1)
. In general, if we set a = 2^(floor(log(n)))
, then F(n) = F(a-1) + F(n-a) + (n-a+1)
This doesn't quite give us an O(log n)
algorithm; however, doing so is easy. If a = 2^x
, then note in the table above that for a-1
, the first bit is set exactly a/2
times, the second bit is set exactly a/2
times, the third bit... all the way to the x'th bit. Thus, F(a-1) = x*a/2 = x*2^(x-1)
. In the above equation, this gives us
F(n) = x*2x-1 + F(n-2x) + (n-2x+1)
Where x = floor(log(n))
. Each iteration of calculating F
will essentially remove the MSB; thus, this is an O(log(n))
algorithm.
Let k
be the number of bits needed for n
.
for 0,...,2^(k-1)-1
each bit is up exactly for half of the numbers, so we have (k-1)*2^(k-1)/2 = (k-1)*2^(k-2)
bits up so far. We only need to check what's up with the numbers that are bigger then 2^(k-1)-1
We also have for those n-2^(k-1)-1
bits "up" for the MSB.
So we can derive to the recursive function:
f(n) = (k-1)*2^(k-2) + n-(2^(k-1)-1) + f(n-(2^(k-1)))
^ ^ ^
first MSBs recursive call for
2^(k-1)-1 n-2^(k-1) highest numbers
numbers
Where base is f(0) = 0
and f(2^k) = k*2^(k-1) + 1
[as we seen before, we know exactly how much bits are up for 2^(k-1)-1
, and we just need to add 1 - for the MSB of 2^k
]
Since the value sent to f
is reduced by by at least half at every iteration, we get total of O(logn)
Here is my solution to this. Time complexity : O (Log n)
public int countSetBits(int n){
int count=0;
while(n>0){
int i= (int)(Math.log10(n)/Math.log10(2));
count+= Math.pow(2, i-1)*i;
count+= n-Math.pow(2, i)+1;
n-= Math.pow(2, i);
}
return count;
}
Not sure if its late to reply, but here are my findings.
Tried solving the problem with following approach, for number N every bitno ( from LSB to MSB, say LSB starts with bitno 1 and incrementing with next bit value) number of bits set can be calculated as , (N/(2 topower bitno) * (2 topower bitno-1) + { (N%(2 topower bitno)) - [(2 topower bitno-1) - 1] }
Have written recursive function for it C/C++ please check. I am not sure but I think its complexity is log(N). Pass function 2 parameters, the number (no) for which we want bits to be calculated and second start count from LSB , value 1.
int recursiveBitsCal(int no, int bitno){
int res = int(no/pow(2,bitno))*int(pow(2,bitno-1));
int rem1 = int(pow(2,bitno-1)) -1;
int rem = no % int(pow(2,bitno));
if (rem1 < rem) res += rem -rem1;
if ( res <= 0 )
return 0;
else
return res + recursiveBitsCal(no, bitno+1);
}