package com.freetymekiyan.algorithms.level.medium;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* 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.
* <p>
* Example:
* For num = 5 you should return [0,1,1,2,1,2].
* <p>
* Follow up:
* <p>
* 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:
* <p>
* 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?
* <p>
* Tags: Dynamic Programming, Bit Manipulation
* Similar Problems: (E) Number of 1 Bits
*/
public class CountingBits {
private CountingBits c;
/**
* DP.
* Recurrence Relation: f[i] = f[i / 2] + i % 2.
* It means that we can decompose the binary string of current integer into two parts:
* 1) the rightmost bit
* 2) from the second rightmost bit to the leftmost bit
* For example: if i = 5, the binary string is 101, "10" + "1"
* So the number of bits relates to the # of bits of i / 2, and whether it's odd or even.
* If it's even, it has the same number of bits as "10", which is 1.
* If it's odd, it has one more, which is 2.
*/
public int[] countBits(int num) {
int[] res = new int[num + 1];
for (int i = 1; i < res.length; i++) {
res[i] = res[i / 2] + i % 2;
}
return res;
}
@Before
public void setUp() {
c = new CountingBits();
}
@Test
public void testExamples() {
Assert.assertArrayEquals(new int[]{0, 1, 1, 2, 1, 2}, c.countBits(5));
}
@After
public void tearDown() {
c = null;
}
}