The basic approach to evaluate the binary form of a number is to traverse on it and count the number of ones. But this approach takes log2N of time in every case.

Why log2N ?

As to get a number in its binary form, we have to divide it by 2, until it gets 0, which will take log2N of time.

With bitwise operations, we can use an algorithm whose running time depends on the number of ones present in the binary form of the given number. This algorithm is much better, as it will reach to logN, only in its worst case.

int count_one (int n)

{

while( n )

{

n = n&(n-1);

count++;

}

return count;

}

Why this algorithm works ?

As explained in the previous algorithm, the relationship between the bits of x and x-1. So as in x-1, the rightmost 1 and bits right to it are flipped, then by performing x&(x-1), and storing it in x, will reduce x to a number containing number of ones(in its binary form) less than the previous state of x, thus increasing the value of count in each iteration.

Example:

n = 23 = {10111}2 .

1. Initially, count = 0.

2. Now, n will change to n&(n-1). As n-1 = 22 = {10110}2 , then n&(n-1) will be {101112 & {10110}2, which will be {10110}2 which is equal to 22. Therefore n will change to 22 and count to 1.

3. As n-1 = 21 = {10101}2 , then n&(n-1) will be {10110}2 & {10101}2, which will be {10100}2 which is equal to 20. Therefore n will change to 20 and count to 2.

4. As n-1 = 19 = {10011}2 , then n&(n-1) will be {10100}2 & {10011}2, which will be {10000}2 which is equal to 16. Therefore n will change to 16 and count to 3.

5. As n-1 = 15 = {01111}2 , then n&(n-1) will be {10000}2 & {01111}2, which will be {00000}2 which is equal to 0. Therefore n will change to 0 and count to 4.

6. As n = 0, the the loop will terminate and gives the result as 4.

Complexity: O(K), where K is the number of ones present in the binary form of the given number. To check if the ith bit is set or not (1 or not), we can use AND operator. How?

Let's say we have a number N, and to check whether it's ith bit is set or not, we can AND it with the number 2i . The binary form of 2i contains only ith bit as set (or 1), else every bit is 0 there. When we will AND it with N, and if the ith bit of N is set, then it will return a non zero number (2i to be specific), else 0 will be returned.

Using Left shift operator, we can write 2i as 1 << i . Therefore:

bool check (int N)

{

if( N & (1 << i) )

return true;

else

return false;

}

Example:

Let's say N = 20 = {10100}2. Now let's check if it's 2nd bit is set or not(starting from 0). For that, we have to AND it with 22 = 1<<2 = {100}2 .

{10100} & {100} = {100} = 22 = 4(non-zero number), which means it's 2nd bit is set. A big advantage of bit manipulation is that it can help to iterate over all the subsets of an N-element set. As we all know there are 2N possible subsets of any given set with N elements. What if we represent each element in a subset with a bit. A bit can be either 0 or 1, thus we can use this to denote whether the corresponding element belongs to this given subset or not. So each bit pattern will represent a subset.

Consider a set A of 3 elements.

A = {a, b, c}

Now, we need 3 bits, one bit for each element. 1 represent that the corresponding element is present in the subset, whereas 0 represent the corresponding element is not in the subset. Let's write all the possible combination of these 3 bits.

0 = (000)2 = {}

1 = (001)2 = {c}

2 = (010)2 = {b}

3 = (011)2 = {b, c}

4 = (100)2 = {a}

5 = (101)2 = {a, c}

6 = (110)2 = {a, b}

7 = (111)2 = {a, b, c}

public static void possibleSubsets(char[] A) {

int N = A.length;

for(int i = 0; i < (1 << N); i++) {

for (int j = 0; j < N; j++) {

if((i & (1 << j)) > 0) {

System.out.print(A[j] + " ");

}

}

System.out.println();

}

}