Sunday, September 25, 2016

Tree & Binary Search Tree

[greeksforgreeks] A program to check if a binary tree is BST or not.

The following are the best solution greeksforgreeks provided.

Solution 1:
  Using in order traversal, and store the result in a auxiliary three element array, if the array is sorted in ascending order, the tree is BST.
  or we can optimization the space like:


[code]
bool isBST(Node *root)
{
     static struct Node *prev = NULL;
     if (root)
     {
         if(!isBST(root->left))
             return false;
         if ( prev != NULL && root->value <= prev->value)
             return false;
         prev = root;
         return isBST(root->right);
     }
     return true;

}


Find lowest common ancestor of two nodes in a binary tree.

Solution:
    Need to implement a helper function which find if a node is a child of the root node.


[code]

bool Has(Node *r, Node *p)
{
    if (r == NULL) return false;
    if (r == p) return true;
    return Has(r->left, p) || Has(r->right, p);
}

Node *LCA(Node *r, Node *p, Node *q)
{
    if (Has(r->left, p) && Has(r->left, q)) 
       return LCA(r->left, p, q);
    if (Has(r->right, p) && Has(r->right, q))
       return LCA(r-right, p, q);
    return r;
}


Find level of a node in a binary tree.

Solution:
[code]
int  findLevel(Node *r, Node *p, int level)
{
    if (root == NULL)
        return -1;
    if ( root == p ) return level;

    int ll = findLevel(root->left, p, level+1);
    if (ll != -1)  return ll;
    return findLevel(root->right, p, level+1);
}



Find Distance between two nodes in a binary tree.

Solution:
   formula: Dist(p,q) = Dist(r,p) + Dist(r,q) - 2*Dist(r, lca)

[Code] 
int Distance(Node *r, Node *p, Node *q) 
{ 
    Node *lc = LCA(r, p, q);
    int Distrp = findLevel(r, p, 0);
    int Distrq = findLevel(r, q, 0);
    int Distlca = findLevel(r, lc, 0);
    return Dist(r, p) + Dist(r, q) - 2* Dist(r, lc);
}

Binary tree iterative pre-order traversal.

Solution:
    using a auxiliary stack

[Code]
void Preorder(Node *r)
{
    stack<Node*>s;
    Node *c;
    s.push(r);
    while(!s.empty()) {
       Node *t = s.top();
       // print out the value of the Node
       cout << t->value << endl;
       s.pop();
       if(t->right) s.push(t->right);
       if(t->left) s.push(t->left);
    }
}




Binary tree iterative post-order traversal.


Solution:
    using two auxiliary stacks


[Code]

void Postorder(Node *r)
{
    Node *c;
    stack<Node*>s;
    stack<Node*>output;
    s.push(r);
    while(!s.empty()) {
       Node *t = s.top();
       output.push(t);
       s.pop();
       if(t->left) s.push(t->left);
       if(t->right) s.push(t->right);
    }
    while(!output.empty()) {
       cout << output.top()->value << endl;
       output.pop();
    }
}

Binary tree iterative in-order traversal.

Solution:
     using one auxiliary stack.
       
[code]
void Inorder(Node *r)
{
    Node *c = r;
    stack<Node *> s;
    while(1) {
      if(c) {
         s.push(c);
         c = c->left;
      }
      else{
         if (s.empty()) break;
         c = s.top();
         cout << c->value << endl;
         s.pop();
         c = c->right;
      }
    }
}


Traverse a binary tree level by level
.

Solution:
    1. find the max height of the tree;
    2. print the tree level indexed by the level index;


[code]
int TreeHeight( Node *r)
{
    if (r == NULL) return 0;
    return max(TreeHeight(r->left), TreeHeight(r->right)) + 1; 
}

void printLevel(Node *r, int level)
{
     if (r==NULL) return;
     if ( level <0 ) return;
     if (level == 0)
          cout << r->value <<endl;
     printLevel(r->left, level - 1);
     printLevel(r->right, level - 1);
}


Find number of leaves in a binary tree.

Solution1:


[code]
int findLeaves(Node *r)
{
    if (r == NULL) return 0;
    if (r -> left == NULL && r->right == NULL) return 1; 
    return findLeaves(r->left) + findLeaves(r->right); 
}

Solution2: using static variable


[code]
int findLeaves(Node *r)
{
    static int count = 0;
    if (r == NULL) return count;
    if (r -> left == NULL && r->right == NULL) count ++; 
    return findLeaves(r->left) + findLeaves(r->right); 
}

Clone a binary tree

Solution: using recursive method;

[code]

struct Node {
      int value;
      Node *left;
      Node *right;
};
    
Node *cloneBinaryTree(Node *r)
{
    if (r==NULL) return NULL;
    Node *p = new Node;
    p->value = r->value;
    p->left = cloneBinaryTree(r->left);
    p->right = cloneBinaryTree(r->right);
    return p;
}







Friday, September 23, 2016

Binary Search

[Google] Binary Search related problem:

      Given an sorted array = {1.2, 7.5, 9.3, 10.2 } and  number x = 8.2, please find a closest element from the array.

Solution:

For the generic binary search framework template:
       int binarysearch( vector<int> &nums, int x)
       { 
           int start = -1;
           int end = nums.size();
           int mid;
           while(end - start > 1) {
             mid = (start + end )/2;
             if (nums[mid] > x) {
                 end = mid;  
             } 
             else {
                 start = mid;
             }
        }

Let's see how this problem fits into the framework.


[Code]
float Solution(vector <float> &nums, float x)
{
     int start = -1;
     int end  = nums.size();
     int mid;
     while(end - start > 1) {
         mid = (end + start)/2;
         if ( nums[mid] > x ) {
             end = mid;
         }
         else {
            start = mid;
         }
     }
     return (x - nums[start]) > (nums[end] -x) ? nums[end]: nums[start];
}

Square Root of X
Implement float sqrt (float x). Compute and return the square root of x.
here x > 1

Solution:

[Code]
float FindSqrt(float x)
{
     float start = -1;
     float end = x;
     float mid;
     while(end - start > 0.01) {
        mid = (end + start) /2;
           if( mid *mid  > x)
               end = mid;
           else start = mid;
     }
     return mid;
}

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;
}








       

   
   

Wednesday, September 21, 2016

C++ Review Points

constructor/deconstructor:

[review points]:
1) several type of constructors:
   default constructor
   parameterized constructor
   copy constructor
how are these constructors got called?
2) why virtual deconstructor? 

[code]
class Base{
    private:
        int member;
    public:
        Base(void) = default;
        Base(int v):member(v){};
        Base(const Base &b)
        {
           member = b.member;
        }
        Base &operator= (const Base &b)
        {
           member = b.member;
           return *this;
        }
        virtual ~Base(void){}
};

 inheritence:

[review points]:


type casts:

static_cast



static_cast is used for cases where you basically want to reverse an implicit conversion, with a few restrictions and additions. static_cast performs no runtime checks. This should be used if you know that you refer to an object of a specific type, and thus a check would be unnecessary. 



Example:

void func(void *data) {
  // Conversion from MyClass* -> void* is implicit
  MyClass *c = static_cast<MyClass*>(data);
  ...
}

int main() {
  MyClass c;
  start_thread(&func, &c)  // func(&c) will be called
      .join();
}

In this example, you know that you passed a MyClass object, and thus there isn't any need for a runtime check to ensure this.

dynamic_cast


dynamic_cast is used for cases where you don't know what the dynamic type of the object is. You cannot use dynamic_cast if you downcast and the argument type is not polymorphic. An example:

if(JumpStm *j = dynamic_cast<JumpStm*>(&stm)) {
  ...
} else if(ExprStm *e = dynamic_cast<ExprStm*>(&stm)) {
  ...
}

dynamic_cast returns a null pointer if the object referred to doesn't contain the type casted to as a base class (when you cast to a reference, a bad_cast exception is thrown in that case).

The following code is not valid, because Base is not polymorphic (it doesn't contain a virtual function):

struct Base { };
struct Derived : Base { };
int main() {
  Derived d; Base *b = &d;
  dynamic_cast<Derived*>(b); // Invalid
}

An "up-cast" is always valid with both static_cast and dynamic_cast, and also without any cast, as an "up-cast" is an implicit conversion.
Regular Cast

These casts are also called C-style cast. A C-style cast is basically identical to trying out a range of sequences of C++ casts, and taking the first C++ cast that works, without ever considering dynamic_cast. Needless to say, this is much more powerful as it combines all of const_cast, static_cast and reinterpret_cast, but it's also unsafe, because it does not use dynamic_cast.

In addition, C-style casts not only allow you to do this, but they also allow you to safely cast to a private base-class, while the "equivalent" static_cast sequence would give you a compile-time error for that.

Some people prefer C-style casts because of their brevity. I use them for numeric casts only, and use the appropriate C++ casts when user defined types are involved, as they provide stricter checking.

const cast


This one is primarily used to add or remove the const modifier of a variable.

const int myConst = 5;
int *nonConst = const_cast<int*>(&myConst); // removes const

Although const cast allows the value of a constant to be changed, doing so is still invalid code that may cause a run-time error. This could occur for example if the constant was located in a section of read-only memory.

*nonConst = 10; // potential run-time error

Const cast is instead used mainly when there is a function that takes a non-constant pointer argument, even though it does not modify the pointee.

void print(int *p) 
{
   std::cout << *p;
}

The function can then be passed a constant variable by using a const cast.

print(&myConst); // error: cannot convert 
                 // const int* to int*

print(nonConst); // allowed

regular cast

These casts are also called C-style cast. A C-style cast is basically identical to trying out a range of sequences of C++ casts, and taking the first C++ cast that works, without ever considering dynamic_cast. Needless to say, this is much more powerful as it combines all of const_cast, static_cast and reinterpret_cast, but it's also unsafe, because it does not use dynamic_cast.In addition, C-style casts not only allow you to do this, but they also allow you to safely cast to a private base-class, while the "equivalent" static_cast sequence would give you a compile-time error for that.Some people prefer C-style casts because of their brevity. I use them for numeric casts only, and use the appropriate C++ casts when user defined types are involved, as they provide stricter checking.

operator overload:

class Complex {
private:
int _a, _b;
public:
Complex(int a=0, int b=0):_a(a),_b(b){};

// 1. over loading syntax

const Complex operator + (const Complex &c) 
{
return Complex(_a+c._a, _b+c._b);
}

Complex & operator += (const Complex &c)

{
_a += c._a; 
       _b += c._b;
return *this; 
}

// 2. unary operator overloading


const Complex operator -() const

{
return Complex(-_a, -_b);


const Complex operator ++() 

{
return Complex(++_a, ++_b);
}
const Complex operator ++(int)
{
return Complex(_a++, _b++);


const Complex operator --() 

{
return Complex(--_a, --_b);
}
const Complex operator --(int)
{
return Complex(_a--, _b--);


// 3. binary operator overloading

friend const Complex operator +( const Complex &left, const Complex &right)
{
return Complex(left._a + right._a, left._b + right._b);
}

// 4. iostream overloading

friend ostream & operator << ( ostream &os, const Complex &c)
{
os << "Complex:" << c._a <<"+" << c._b << endl;
return os;
}

#if 0
friend istream &operator >> ( istream &is, Complex &c)
{
     is >> c._a >> c._b;
     return is;
}
#endif

friend istream &operator >> (istream &is, Complex &c)

{
    string mystr;
    cout << "first ele";
    
    getline(is, mystr);
    stringstream(mystr) >> c._a;
    cout << "second ele";
    getline(is, mystr);
    stringstream(mystr) >> c._b;
    return is;
}
};

functor

class Fctor {
    private:
         int m;
    public:
         Fctor(int x):m(x){};
         int operator() (int y) { return m + y; }
};


int main(void)

{
     Fctor a(10);
     cout << a(20) << endl;
     return 0;
}

smart pointer:


class TBase {
public:
TBase(void){ cout << "TBase ctor" << endl; }
        void display() { cout << "Display" << endl; }
~TBase(void) { cout << "TBase dtor" << endl; }
};


void rawfunction(void)
{
       TBase *tb = new TBase;
}

void scopedfunction(void)
{
unique_ptr<TBase> ptr (new TBase);
        ptr -> display();
}

shared_ptr<TBase> sharedfunction(void)
{
shared_ptr<TBase>ptr (new TBase);
        shared_ptr<TBase> ptr1 = ptr;
ptr ->display();
        return ptr1;
}

void autofunction(void)
{
auto_ptr<TBase>ptr(new TBase);
ptr->display();
}

void weakfunction(void)
{
        shared_ptr<TBase>sptr ( new TBase);
    weak_ptr<TBase>ptr = sptr;
//        cout << "weaked_ptr: is" << ptr << endl;
sptr->display();
}

void uniquefunction(void)
{
     unique_ptr <TBase> uptr ( new TBase);
     unique_ptr <TBase> wptr;
     wptr = move(uptr);
     wptr->display();
}



int main(void)
{
    shared_ptr<TBase>ptr;

    rawfunction();
    cout <<"XXXXX" << endl;
    scopedfunction();

    cout <<"XXXXX" << endl;
    ptr= sharedfunction();

    cout <<"XXXXX" << endl;
    autofunction();

    cout <<"XXXXX" << endl;
    weakfunction();

    cout <<"XXXXX" << endl;
    uniquefunction();
    return 1;
}


template/stl


sizeof



reference


I/O



binding (c++11)



exceptions


RAII


design patterns