Showing posts with label bit manipulation. Show all posts
Showing posts with label bit manipulation. Show all posts

Thursday, October 6, 2016

N Queen Problem

N Queen Problem:

Solutions:

   The entire chessboard should be stored as an 1-dimensional array with the length of N, and is represented with A[N]. The value of the i-th element in A[i] represents the queen column position of the i-th row.

    For example:  A[5] = 3 represents a position of (5,3), the 5th row and the 3rd column.    
So, given arbitrary two rows: i,j (i!=j) and it corresponding two cols should be: A[i], A[j].

The conflict should happen in one of the cases:

1) A[i] == A[j]   column conflict case;
2) A[i] - A[j] == (i - j) or (j - i) two diagonal conflict cases;

So the first step is to find out if we can place a queen in (row, col) 
the algorithm should be:

[code]

bool OKtoPlace(int row, int col)
{ 
     for (int r = 0; r < row; r++) {
        if (A[r] == col || A[r] - col ==  row - r || A[r] - col == r - row)
               return false;
      }
      return true;
}

   The next step is how to find all possible solutions. This is a classic backtracking algorithm, there are two ways for implementation, recursive and non-recursive. and rescursive method is relatively simple, here is the workflow:
       
[code]
void Queen(int row)
{
    if (n == row) {     // if all row are done, print out result;                  
       count ++;       // a new possible solution found. 
       print_result();
    }
    else {
       for (int col = 0; col < N; col++) {    //try each col on the row
            if (can_place(row, col) {  // is it ok to set the queen on (row, col) ?
                   place(row, col);    // set the queen
                   queen(row + 1);     // move to the next row
             }
        }
}
 


Now combine the above two steps we get
Solution 1:
       
[code]

const int N = 8;
int A[N];
int count = 0;

void print_out(void){
    for(int r=0; r<N; r++){
        for(int c=0; c<N; c++){
            if(c == A[r]) cout<< "Q ";
            else cout<< "0 ";
        }
        cout<<endl;
    }
    cout<<endl;
}

bool OktoPlace(int row, int col)
{
    for (int r= 0; r<row; r++) {
        if (A[r] == col || A[r] -col == row -r || A[r] - col == row - r)
           return false;
    }
    return true;
}

void queen(int row)
{
    if(row == N) {
       count ++;
       print_out();
       return;
    }

    for (int col = 0; col < N; col++) {
         if(OktoPlace(row, col)) {
             A[row] = col;
             queen(row + 1);
        }
    }
}

int main(void)
{
    queen(0);
    cout << count << endl;
    return 0;
}

         


Now let's see if we can optimize the core algorithm.

Solution 2:

As we can see that in the above function OKtoPlace(int row, int col), the time complexity is O(N), we can reduce it to O(1) by introducing two extra 1-dimensional bool arrays: P, Q.  Each represents the diagonal elements of a position, so the sizeof P and Q is 2N-1. Now for any position [row, col] on the board, we need to check if any one of 
[col, row+col, N-1 +col + row]
has a conflict.

So for each given row, we can replace place() function with one compound statement:
[code]

bool C[N], P[2*N-1], Q[2*N-1];

C[col] = true; P[row+col] = true; Q[N-1+col-row] = true;

     

Same with can_place()function, for each given row, we can replace can_place() function with one compound statement:
[code]

if (C[col] == true || P[row+col] == true || Q[N-1+col-row] == true)  //conflict
else  // no conflict and good to place.    


So the whole program becomes:
[code]
const int N = 8;
bool C[N], P[2*N-1], Q[2*N-1];

int count = 0;

void queen(int row)
{
    if (row == N) {
       count ++;
       return;
    }
    for (int col = 0; col < N; col++) {
        if (C[col] || P[row + col] || Q[N-1 + col - row]) continue; //conflict on this position
        C[col] = true; P[row+col] = true; Q[N-1+col-row] = true;
        queen(row + 1);
        C[col] = false; P[row+col] = false; Q[N-1+col-row] = false;
    }
}


Solution 3:
we can replace these three 1 dimensional Boolean arrays with only three integers C,P,Q , each bit in [C,P,Q] represents 
[col, row+col, N-1 +col + row] like above:

So the whole program becomes:
[code]

const int N = 8;
int C, P, Q;

int count = 0;

void queen(int row)
{
    if (row == N) {
       count ++;
       return;
    }
    for (int col = 0; col < N; col++) {
        if ( (C>>col) &1|| P>>(row + col) & 1 || Q >> (N-1 + col - row) & 1) continue;
        C ^= (1 << col);  P ^=(1 << (row+col)); Q ^= ( 1 << (N-1+col-row));
        queen(row + 1);
        C ^= (1 << col);  P ^=(1 << (row+col)); Q ^= ( 1 << (N-1+col-row));
    }
}




Thursday, September 22, 2016

Find Missing or Duplicate Number

[GreektoGreek] Find the Missing Number (or Duplicate Number), Solutions

   You are given a list of n-1 integers and these integers are in the range of 1 to n. There are no duplicates in list. one of the integers is missing in the list. Write an efficient code to find the missing integer.

For example: given array = [1,2,4, , 6, 3, 7, 8]

the result should be: 5


Solution 1: calculate sum from 1 to n and subtract each element from the array, the remain number is the result. Time complexity O(n).


[Code]
int Solution1(vector <int> &num, int N)
{
     int len = num.size();
     int sum = (N + 1) * N / 2;
     for(int i= 0; i< len; i++) {
         sum -= num[i];
     }
     return sum;
}


Solution 2: calculate xor sum from 1 to n and xor again with each element from the array, the remain number is the result. Time complexity: O(n).



[Code]
int Solution2(vector<int> &num, int N)
{
    int len = num.size();
    int sum = 0;
    for(int i=1; i<=N; i++)
       sum ^= i;
    for(int i= 0; i< len; i++)
       sum ^=num[i];
    return sum;
}

Solution 3: sort the whole array and compare element from 1 to n-1
if find there is a mismatch, just return the value i+1. Time complexity: O(nlogn).

[Code]
int Solution3( vector<int> & num, int N)
{
    sort(num.begin(), num.end());
    for( int i= 0; i< N-1; i++)
      if( (i+1) != num[i])
         return i+1;
}

Solution 4: Sort the whole array (O(n)) in this case and then find out the missing number:


[Code]
int Solution4(vector<int> & num, int N)
{
    int r= 0;
    while(r<N) {
      if (num[r] <N-1 && num[r] !=num[num[r]-1])
          swap(num[r], num[num[r-1]]);
      else
          r ++;
    } 
     
    for( int i= 0; i< N-1; i++)
      if( (i+1) != num[i])
         return i+1;
}



Variety of extended problems:

1. You are given a list of n-2 integers and these integers are in the range of to n. There are no duplicates in list. 2 of the integers is missing in the list. Write an efficient code to find these missing integers.


Solution 1: (No code example)


Multiply and addition, let's assume that the two unknown numbers are A, B;


1) Calculate P = 1*2*...n and divided by each element from array, 

   get P = A * B;

2) Calculate S = 1+2+...+ n and subtracted by each element from array, 

   get S = A + B;

3) Combine S and P we get A and B,



Solution 4:  (time complexity O(n))


1) Calculate X = 1^2^...n, then calculate X xor each element from the array, and get X = A^B , this X indicates the different of A and B on the bit level;


2) use the bit operation to find out the number only contains the right most bit set of X and yield Y;

   get Y = X&(~X + 1)

3) using Y to divide the whole array into two groups and repeat 1) 

to separate A and B; 
     
[Code]
void Solution(vector<int> &nums, int N, int &a, int &b)
{
     int len = nums.size();
     int sum = 0;
     for( int i = 1; i<=N; i++)
        sum ^= i;
     for(int i = 0; i< len; i++)
        sum ^= nums[i];

     sum = sum &(~(sum -1)); 

     a = b = 0;

     for(int i=1; i<=N; i++)
        if((i & sum) == sum)
           a = a ^i;
        else
           b = b^i;

     for( int i = 0; i< len; i++)
        if( (nums[i] & sum) == sum)
            a = a ^ nums[i];
        else
            b = b ^ nums[i];

}


2. You are given an array of n+2 elements. All elements of the array are in range 1 to n. And all elements occur once except two numbers which occur twice. Find the two repeating numbers.

For example, array = {4, 2, 4, 5, 2, 3, 1} and n = 5
The above array has n + 2 = 7 elements with all elements occurring once except 2 and 4 which occur twice. So the output should be 4 2.

Solution:
   This is exactly the same as problem 1, because after xor the whole array, result does not include these repeated numbers, X^X = 0.

3. Find the repeating and the missing, you are given an array of size n. Array elements are in range from 1 to n. One number from set {1, 2, …n} is missing and one number occurs twice in array. Find these two numbers.
Solution 1:
   This is exactly the same as the problem 1, because after xor the whole array, result does not include these repeated numbers, X^X = 0. (it does not ask which number is missing and which number appears twice). 






Solution 2: 
    Using auxiliary array, space O(n), time complexity O(n).
1) create an auxiliary array with size of array + 1 and initialize all of these elements to 0;
2) iterate all elements from array and increase the value of its corresponding aux elements;
3) iterate all elements from aux array, find the elements with 0 and 2 values; 



[Code]
int Solution(vector<int> & nums, int &dup, int &missing)
{
    vector<int> aux (nums.size()+1, 0);
    for (int i= 0; i< nums.size(); i++) {
         aux[nums[i]] ++;
    }

    for (int i= 1; i< aux.size(); i++) {
        if (aux[i] == 0) missing = i;
        if (aux[i] == 2) dup = i;
    }
}


4. Find a missing element in the sorted array, array elements are in range from 1 to n-1, using the most efficient way. 


For example: given an array[] = {1,2,3,4,5,7,8,9,10};  call the function should return 6;


Solution: time complexity O (log(n)):

Using binary search


  
int Solution(vector<int> & nums)
{
    int len = nums.size();
    int l = 0;
    int r = len -1;
    int mid;
    while(r>0 && l < len){
       mid = (r+l)>> 1;
       if( nums[mid] == mid+1 && nums[l] == l+1) {
           l = mid+1;
       }
       else r = mid;
       if ( r== l) break;
    }
    return r + 1;
}



5. Find a duplicate element in the sorted array, array elements are in range from 1 to n, using the most efficient way. 

For example: given an array[] = {1,2,3,4,4,5,6,7,8,9,10};  call the function should return 4;

Solution: time complexity O (log(n)):
Using binary search

 [Code] 
int Solution(vector<int> & nums)
{
    int len = nums.size();
    int l = 0;
    int r = len -1;
    int mid;
    while(r>0 && l < len){
       mid = (r+l)>> 1;
       if( nums[mid] == mid+1 && nums[l] == l+1) {
           l = mid+1;
       }
       else r = mid;
       if ( r== l) break;
    }
    return r;   // only this statement is different from the previous problem. :)
}



6. [GeeksforGeeks] Find the element that appears once.
Given an array where every element occurs three times, except one element which occurs only once. Find the element that occurs once. Expected time complexity is O(n) and O(1) extra space.
Examples:
Input: arr[] = {12, 1, 12, 3, 12, 1, 1, 2, 3, 3}

Output: 2
Solutions:
   This is a very tricky solution, which requires we understand very well about the xor and bit operations:

    Trick 1:  if X = 0, then set X = a  by assigning X = X | a on the bit level.


   Trick 2:   if Y = a, then reset Y = 0 by assigning Y = Y ^ a  on the bit level.
             if Y = 0, then reset Y= a by  assigning Y= Y ^ a on the bit level.

   Trick 3:  if Z = a & b, then reset a = 0 by assigning a = ~Z & a  on the bit level.



int Solution(vector<int> & nums)
{
      int    ones = 0 ;
      int    twos = 0 ;
      int    threes = 0;
      int x ;

      for( i=0; i< nums.size(); i++ )
      {
           x =  nums[i];
          
           // calculate twos first because it requires the previous value of ones
           twos = twos | (ones & x) ;
          
           // set/reset ones 
           ones = ones ^ x ;
           
           // if both ones and twos are set, counts threes 
           threes = ones & twos ;

           // now if threes is set for value x, clear the ones and twos
           ones = ones & ~threes ;
           twos = two & ~ threes ;
       }
        return ones;
}








       

   
   

Friday, July 29, 2016

Bit Manipulations

Basic bitwise operations: 

&   -  bitwise and
|   -  bitwise or
^   -  bitwise xor
~   -  bitwise not
<<  -  bitwise shift left
>>  -  bitwise shift right

various bit operations problems:

1. check odd or even integer:

[code]
    (x & 1) == 1 // is odd else even

2. check the n-th bit is set or not:

[code]
    (x >>n ) &  1 == 1 // is set else not set

3. set the n-th bit:

[code]
    x | (1<<n)

4. unset the n-th bit:

[code]
    x & ~(1<<n)


5. toggle the n-th bit:

[code]
    x ^(1<<n)


6. turn off the rightmost 1-bit:
For example, given an integer 00101010, it turns into 00101000.


[code]
    x & (x-1)


7. isolate the rightmost 1-bit:
For example, given an integer 01010100, gets value: 00000100.


[code]
    x & (-x)

8. right propagate the rightmost 1-bit:
Given a value 01010000 turns into 01011111. All the 0-bits right to the right most 1-bit get turned into ones. 

[code]
    x | (x-1)


9. Isolate the rightmost 0-bit:
For example, this number 10101011, producing 00000100.
[code]
   ~x & (x+1)

10. Turn on the rightmost 0-bit:
For example, given an integer 10100011 turns into 10100111.
[code]
   x | (x+1)


11. Implement addition using only bitwise operators:



[code]
int BitAdd(int a, int b)
{
    int carry = a & b;
    int result = a ^ b;
    int shiftcarry;
    while (carry != 0) {
        shiftcarry = carry << 1;
        carry = result & shiftcarry;
        result = result ^ shiftcarry;
    }
    return result;

}
 


12. Implement subtraction using only bitwise operators:
Based on the previous function BitAdd(), we have,

[code]


int BitSub(int a, int b)   // a - b
{ 
     int nb = BitAdd(~b, 1);    // b --> -b
     return BitAdd(a, nb);      // a-b = a+ (-b)
  
}
 

13. Implement multiplication using only bitwise operators:

[code]

int BitMul(int a, int b)
{
        bool isNeg = (a > 0) ^ (b > 0);
        unsigned int x = a > 0 ? a : BitAdd(~a,1);
        unsigned int y = b > 0 ? b : BitAdd(~b,1);
        int ans = 0;
        while (y)
        {
                if (y & 0x01) ans = Add(ans, x);
                y >>= 1, x <<= 1;
        }
        return isNeg ? BitAdd(~ans, 1) : ans;
}

14. Implement division using only bitwise operators:

[code]

int BitDiv(int a, int b)   // b !=0
{
        bool isNeg = (a > 0) ^ (b > 0);
        unsigned int x = a > 0 ? a : BitAdd(~a,1);
        unsigned int y = b > 0 ? b : BitAdd(~b,1);
        int ans = 0;
        for (int i = 31; i >= 0; i--)
            if ((x >> i) >= y) {     //x >= (y << i) // avoid overflow
               x = BitSub(x, y << i),
               ans = Add(ans, 1 << i);
             }
        return isNeg ? BitAdd(~a,1) : ans;
}
                              

15. Implement a to the power of b using bitwise operators:


[code]

int BitPow(int a, int b)
{
        int ans = 1, q = a;
        while (b)
        {
                if (b & 0x01) ans = BitMul(ans, q);
                b >>= 1;
                q = BitMul(q, q);
        }
        return ans;
}
                     


16. Swap odd and even bits in an integer (eg. bit 0 and bit 1 are swapped, bit 2 and bit 3 are swapped):



[code]

int OddEvenBitSwap(int x)
{
   return ((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)
}
                     


17. Check if binary representation of a number is palindrome. Given an integer ‘x’, write a C function that returns true if binary representation of x is palindrome else returns false.





[code]
bool ispan(int x)
{
     int p = x;
     int r = 0;

     while(p){
         r = (r<<1) | (p & 0x01);
         p = p >> 1;
     }
     return !(r ^ x);
}
                     

Another way to do it is to one by one compare the most significant bit against the least significant bit.


[code]

bool ispan(int x, int length)
{
     int p = length -1;
     int r = 0;

     while(l>0){
         if( ((x>>l) & 1 ) != ((x >>r) & 1)) return false;
         l --; r ++;
     }
     return true;
}                     

(LintCode) Given two 32-bit numbers, N and M, and two bit positions, i and j. Write a method to set all bits between i and j in N equal to M (e g , M becomes a substring of N located at i and starting at j)

[code]
int bitupdate(int n,  int m, int j, int i)
{
      int mask = (((1 << (j+1)) -1) ^ ( (1<<(i)) -1));
      m = m << i;
      n = n & (~mask);
      n = n | m;
      return n;
}

                     

Using O(1) time to check whether an integer n is a power of 2.


[code]
bool checkpowerof2(int n)
{
      return (n & (n-1)) == 0;
}

                     


Count how many 1 in binary representation of a 32-bit integer.

[code]
bool bitcount(int n)
{
      int count = 0;
      while(n!=0) {
         n = n &(n-1);
         count ++;
      }      
      return count;
}

Determine the number of bits required to flip if you want to convert integer n to integer m.


[code]
bool bitflipnum(int n, int m)
{
      int count = 0;
      n = n ^ m; 
      while(n!=0) {
         n = n &(n-1);
         count ++;
      }      
      return count;
}





A RGB Conversion:

Given a 16-bit integer RGB code, the bit maps are as follows:  

Code = 5(R-bits)6(G-bits)5(B-bits)

Convert it into three 8-bit RGB codes.



Solution:

   1)using bit shift and mask operations to extract each color code;

   2)calculation each scale from 31 (2^5-1) or 63 (2^6-1) to 255 (2^8-1); 

   3)forming a new 24bit RGB code;