Saturday, December 10, 2011

Search an element in sorted rotated array

Problem: Given a sorted rotated array of distinct integers, find out the index of a given integer target in the array. If target does not exist in the array, return -1.


Approach: Using binary search.


Implementation in C#:

    public int Search(int[] nums, int target) 
    {
        int start = 0, end = nums.Length - 1;
        
        while (start <= end)
        {
            int mid = start + (end - start) / 2;
            
            if (nums[mid] == target)
            {
                return mid;
            }
            
            if (nums[start] <= nums[mid])
            {
                if (target >= nums[start] && target < nums[mid])
                {
                    end = mid - 1;
                }
                else
                {
                    start = mid + 1;
                }
            }
            else
            {
                if (target > nums[mid] && target <= nums[end])
                {
                    start = mid + 1;
                }
                else
                {
                    end = mid - 1;
                }
            }
        }
        
        return -1;
    }


Complexity: O(logn)

Tuesday, December 6, 2011

5 Pirates and 100 Gold Coins

Question:
Five pirates got a chest containing 100 gold coins. Now they need to think about a distribution strategy. The pirates are ranked  (Pirate 1 to Pirate 5, where Pirate 5 is the most powerful). The most powerful pirate gets to propose a plan and then all the pirates vote on it. If at least half of the pirates agree on the plan, the gold is split according to the proposal. If not, then that pirate will be killed and this process continues with the remaining pirates until a proposal is accepted. The first priority of the pirates is to stay alive and second to maximize the gold they get. Pirate 5 devises a plan which he knows will be accepted for sure and will maximize his gold. What is his plan? 

Solution:
Reduce this problem to only 2 pirates. So what happens if there are only 2 pirates. Pirate 2 can easily propose that he gets all the 100 gold coins. Since he constitutes 50% of the pirates, the proposal has to be accepted.

Now in 3 pirates situation, Pirate 3 knows that if his proposal does not get accepted, then pirate 2 will get all the gold and pirate 1 will get nothing. So he decides to give one gold coin to Pirate 1 . Pirate 1 knows that one gold coin is better than nothing so he has to back Pirate 3. Pirate 3 proposes {pirate 1, pirate 2, pirate 3} {1, 0, 99}.
If there are 4 pirates, Pirate 4 needs to get one more pirate to vote for his proposal. Pirate 4 knows that if he dies, pirate 2 will get nothing (according to 3 pirates situation) so he will give one gold coin to pirate 2 to get his vote. So the distribution will be {0, 1, 0, 99}.

Now in 5 pirates situation, Pirate 5 needs 2 votes and he knows that if he dies, pirate 1 and 3 will get nothing. so he can give one gold coin to Pirates 1 and 3 to get their vote. In the end, he proposes {1, 0, 1, 0, 98}. 

Tuesday, November 29, 2011

ThoughtWorks Question: Game of Life

Problem: Given a board with m by n cells, each cell has an initial state live (1) or dead (0). Each cell interacts with its eight neighbors (horizontal, vertical, diagonal) using the following four rules:
  1. Any live cell with fewer than two live neighbors dies, as if caused by under-population.
  2. Any live cell with two or three live neighbors lives on to the next generation.
  3. Any live cell with more than three live neighbors dies, as if by over-population..
  4. Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
Write a method to compute the next state (after one update) of the board given its current state. The next state is created by applying the above rules simultaneously to every cell in the current state, where births and deaths occur simultaneously.

Example (Taken from leetcode):

Input: 
[
  [0,1,0],
  [0,0,1],
  [1,1,1],
  [0,0,0]
]
Output: 
[
  [0,0,0],
  [1,0,1],
  [0,1,1],
  [0,1,0]
]


Approach: It can be easily done if we use O(m x n) space, basically copy the input matrix to another matrix of same size and then according to the new matrix, we'll update the original matrix. The problem is we want to avoid the extra space. 

The solution is still very simple. Right now a cell is live when the value is 1 and dead if value is 0. We can use some values say x and y other than these values to denote if a particular cell died (x) or got a life (y) just because of latest iteration.

I am gonna take -1 as x i.e. a cell is recently died. I am taking -1 as it just help while comparing for the live neighbors as what I can say if Abs(board[i][j]) == 1 then neighbor cell at [i][j] is live for this particular iteration. I am gonna take 2 as y i.e. a cell is recently got a life. There is no logic for this, I just chose a positive value to denote live cells.

Now you can see we need two loops here. In the first loop we will assign -1 and 2 according to the given rules if required and in the second loop we will convert -1 to 0 and 2 to 1.

Cheers!


Implementation in C#:

        public void GameOfLife(int[][] board)
        {
            if (board?.Length <= 0 || board[0]?.Length <= 0)
            {
                return;
            }

            for (int i = 0; i < board.Length; ++i)
            {
                for (int j = 0; j < board[0].Length; ++j)
                {
                    bool modified = this.ValidateAndApplyRule1IfNeeded(board, i, j) ||
                    this.ValidateAndApplyRule2IfNeeded(board, i, j) ||
                    this.ValidateAndApplyRule3IfNeeded(board, i, j) ||
                    this.ValidateAndApplyRule4IfNeeded(board, i, j);

                    // Just for debugging purpose
                    // Console.WriteLine($"Cell [{i}][{j}] is modified: {modified}");
                }
            }

            for (int i = 0; i < board.Length; ++i)
            {
                for (int j = 0; j < board[0].Length; ++j)
                {
                    board[i][j] = board[i][j] <= 0 ? 0 : 1;
                }
            }
        }

        private bool ValidateAndApplyRule1IfNeeded(int[][] board, int i, int j)
        {
            if (board[i][j] == 1)
            {
                if (this.CountLiveNeighbors(board, i, j) < 2)
                {
                    board[i][j] = -1;
                    return true;
                }
            }

            return false;
        }

        private bool ValidateAndApplyRule2IfNeeded(int[][] board, int i, int j)
        {
            if (board[i][j] == 1)
            {
                int liveNeighbors = this.CountLiveNeighbors(board, i, j);
                if (liveNeighbors == 2 || liveNeighbors == 3)
                {
                    return true;
                }
            }

            return false;
        }

        private bool ValidateAndApplyRule3IfNeeded(int[][] board, int i, int j)
        {
            if (board[i][j] == 1)
            {
                if (this.CountLiveNeighbors(board, i, j) > 3)
                {
                    board[i][j] = -1;
                    return true;
                }
            }

            return false;
        }

        private bool ValidateAndApplyRule4IfNeeded(int[][] board, int i, int j)
        {
            if (board[i][j] == 0)
            {
                if (this.CountLiveNeighbors(board, i, j) == 3)
                {
                    board[i][j] = 2;
                    return true;
                }
            }

            return false;
        }

        private int CountLiveNeighbors(int[][] board, int i, int j)
        {
            int liveNeighbors = 0;
            if (i > 0)
            {
                liveNeighbors += Math.Abs(board[i - 1][j]) == 1 ? 1 : 0;
            }
            if (j > 0)
            {
                liveNeighbors += Math.Abs(board[i][j - 1]) == 1 ? 1 : 0;
            }
            if (i > 0 && j > 0)
            {
                liveNeighbors += Math.Abs(board[i - 1][j - 1]) == 1 ? 1 : 0;
            }
            if (i < board.Length - 1)
            {
                liveNeighbors += Math.Abs(board[i + 1][j]) == 1 ? 1 : 0;
            }
            if (j < board[0].Length - 1)
            {
                liveNeighbors += Math.Abs(board[i][j + 1]) == 1 ? 1 : 0;
            }
            if (i < board.Length - 1 && j < board[0].Length - 1)
            {
                liveNeighbors += Math.Abs(board[i + 1][j + 1]) == 1 ? 1 : 0;
            }
            if (i < board.Length - 1 && j > 0)
            {
                liveNeighbors += Math.Abs(board[i + 1][j - 1]) == 1 ? 1 : 0;
            }
            if (i > 0 && j < board[0].Length - 1)
            {
                liveNeighbors += Math.Abs(board[i - 1][j + 1]) == 1 ? 1 : 0;
            }

            return liveNeighbors;
        }


Complexity: O(mxn)

Tuesday, November 1, 2011

Infibeam Question: Reverse Level Order Traversal of Binary Tree

void BSTree::reverseLevelOrderTraversal(Node* node)
{
    queue<Node*> qu;
    stack<int> st;
    qu.push(node);
    while(!qu.empty())
    {
        Node* temp = qu.front();
        st.push(temp->data);
        if(temp->right)
            qu.push(temp->right);
        if(temp->left)
            qu.push(temp->left);
        qu.pop();
    }
    while(!st.empty())
    {
        cout<<st.top()<<'\t';
        st.pop();
    }
}

Infibeam Question: Implement T9 Dictionary

Solution is to take hash with key is the number and the value is the list of words which can be made by pressing the digits in the number. For example 4663 --> good, home

LoadWords Operation --

   1. Read words and their popularity one by one from file.
   2. Get the number corresponding to the word.
   3. Make an object which contains the word and its popularity.
   4. hash[number].insert(wordObject).

DisplayWords Operation --

It was given that most popular 5 words need to be displayed.
  1. Maintain a heap based on popularity of size 5.
  2. Maintain the keys in the hash in string sorted order. ( Map can be used for hash)
  3. Look for the keys which are started with the given number.

Source Code --

#include<iostream>
#include<string>
#include<map>
#include<vector>
#include<fstream>
#include<algorithm>

using namespace std;

//Class word
class Word
{
public:
    Word(string w="", int p=0);
    string getWord();
    int getPopularity();
private:
    string word;     //actual word
    int popularity;  //popularity of word
};

Word::Word(string w, int p):word(w), popularity(p)
{
}

string Word::getWord()
{
    return word;
}

int Word::getPopularity()
{
    return popularity;
}

//Comparator function used to sort the vector of Word with key popularity of the word
bool wordCompare(Word a, Word b)
{
    return a.getPopularity() == b.getPopularity() && a.getWord() < b.getWord() || 
    a.getPopularity() > b.getPopularity();
}

//This is helper class to T9Dictionary class. It uses heap to maintain the top 5 i.e. total words to display
class T9DictDisplayHelperHeap
{
public:
    T9DictDisplayHelperHeap(int num = 5);  //num is number of words to display
    void pushHeap(Word word);   //insert word into heap
    void displayWords();        //display the words
private:
    int count;
    vector<Word> vectWord;        //heap
    const short wordsToDisplay;
};

T9DictDisplayHelperHeap::T9DictDisplayHelperHeap(int num):wordsToDisplay(num), count(0)
{
    vectWord.reserve(wordsToDisplay);
}

void T9DictDisplayHelperHeap::pushHeap(Word word)
{
    if(count<wordsToDisplay)
    {
        vectWord.push_back(word);
        count++;
    }
    else if(count == wordsToDisplay)
    {
        make_heap(vectWord.begin(), vectWord.end(), wordCompare);
        if(vectWord.front().getPopularity() < word.getPopularity())
        {
            pop_heap(vectWord.begin(), vectWord.end(), wordCompare);
            vectWord.pop_back();
            vectWord.push_back(word);
            push_heap(vectWord.begin(), vectWord.end(), wordCompare);
        }
        count++;
    }
    else
    {
        if(vectWord.front().getPopularity() < word.getPopularity())
        {
            pop_heap(vectWord.begin(), vectWord.end(), wordCompare);
            vectWord.pop_back();
            vectWord.push_back(word);
            push_heap(vectWord.begin(), vectWord.end(), wordCompare);
        }
    }
}

void T9DictDisplayHelperHeap::displayWords()
{
    if(count < wordsToDisplay)
        sort(vectWord.begin(), vectWord.end(), wordCompare);
    else
    {
        sort_heap(vectWord.begin(), vectWord.end(), wordCompare);
    }
    int size = vectWord.size();
    for(int i = 0; i < size; ++i)
        cout<<vectWord[i].getWord()<<" : "<<vectWord[i].getPopularity()<<'\n';
}

//Dictionary Class. It is using map in which key is the number and the value is vector of corresponding words
class T9Dict
{
public:
    T9Dict(int count = 5);   //count is number of words to display
    bool loadWords(string fileName);   // load words from a file, fileName is the path of the file which contains words to be inserted in dictionary
    void displayWords(string num);       
private:
    const short wordsToDisplay;
    void addWord(string key, Word w);
    map<string, vector<Word> > mapWords;
};

T9Dict::T9Dict(int count):wordsToDisplay(count)
{
}

// For each alphabet it is taking the corresponding number like for a,b,c corresponding number is 2
// For space ' ' number is 0
// For digits number is same as the digit given
// For all other special charcters number is 1

bool T9Dict::loadWords(string fileName)
{
    ifstream in(fileName.c_str());
    if(!in)
    {
        cout<<"File: "<<fileName<<" does not exist or not accessible\n";
        return false;
    }
    int popularity = 0;
    char *temp = new char[256];
    string word;
    while(!in.eof())
    {
        string key = "";
        in>>popularity;
        //in>>word;
        in.getline(temp, 255);
        word.clear();
        word = string(temp);
        word = word.substr(1);
        int len = word.length();
        for(int i=0; i<len; ++i)
        {
            word[i] = tolower(word[i]);
            if(word[i] == ' ')
                key += '0';
            else if(word[i] >= '0' && word[i] <= '9')
            {
                key += word[i];
            }
            else if(word[i] >= 'a' && word[i] <= 'o')
            {
                key += (((word[i] - 'a') / 3) + 2 + '0') ;
            }
            else if(word[i] >= 'p' && word[i] <= 's')
            {
                key += '7';
            }
            else if(word[i] >= 't' && word[i] <= 'v')
            {
                key += '8';
            }
            else if(word[i] >= 'w' && word[i] <= 'z')
            {
                key += '9';
            }
            else
            {
                key += '1';
            }
        }
        addWord(key, Word(word, popularity));
    }

    delete temp;
    for(map<string, vector<Word> >::iterator it = mapWords.begin(); it != mapWords.end(); 
    ++it)
    {
        sort(it->second.begin(), it->second.end(), wordCompare);
    }
    return true;
}

void T9Dict::addWord(string key, Word word)
{
    mapWords[key].push_back(word);
}

void T9Dict::displayWords(string num)
{
    T9DictDisplayHelperHeap heap;
   
    map<string, vector<Word> >::iterator it = mapWords.begin();
    while(it != mapWords.end() && it->first < num)
    {
        it++;
    }
    int len = num.length();
    while(it != mapWords.end() && (it->first.substr(0, len) == num))
    {
        for(unsigned int i=0; i < it->second.size(); ++i)
            heap.pushHeap(it->second[i]);
        it++;
    }

    heap.displayWords();
}

Thursday, October 13, 2011

Informatica Question: Given a transaction log in which each line contains a transaction detail (Customer Id, Customer name, Price), Find out the average price given by a customer.

Solution:

1. Read each line, extract customer id and price.

2. Maintain a hash in which key is customer id and value is pointer to struct defined as below -
    struct details
    {
       long totalPrice;
       int count;
     };

3. For each transaction do
    i.  hash[customerId]->totalPrice += extractedPrice;
    ii. hash[customerId]->count++;

4. Now for given customer, average price = hash[customerId]->totalPrice / hash[customerId]->count;

Wednesday, October 5, 2011

Range Minimum Query

You can find the description and implementation using c++ of Range Minimum Query(RMQ) in the following link -

http://algods-cracker.blogspot.com/p/algorithms.html#RMQ

Knuth-Morris-Pratt Algorithm: String Matching in Linear time

You can find the description and implementation using c++ of Knuth Morris Pratt ( KMP)  in the following link -

http://algods-cracker.blogspot.com/p/algorithms.html#Knuth

Count Sort: Sorting in linear time

You can find the description and implementation using c++ of Count Sort in the following link -

http://algods-cracker.blogspot.com/p/algorithms.html#Count

Tuesday, October 4, 2011

[Amazon] Find Least Common Ancestor of two nodes in a Binary Tree

Problem: Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.

According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”

Example:

Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
Output: 3
Explanation: The LCA of nodes 5 and 1 is 3.
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
Output: 5
Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.
Input: root = [1,2], p = 1, q = 2
Output: 1


Approach: Its an straight forward solution which can be understood by just looking at the code. Please note that we are using Post order traversal approach here.


Implementation in C#:

       public TreeNode LowestCommonAncestor(TreeNode root,
                                         TreeNode p,
                                         TreeNode q)
    {
        if (root == null)
        {
            return null;
        }

        if (root == p || root == q)
        {
            return root;
        }

        TreeNode leftLCA = this.LowestCommonAncestor(root.left, p, q);
        TreeNode rightLCA = this.LowestCommonAncestor(root.right, p, q);
        if (leftLCA != null && rightLCA != null)
        {
            return root;
        }
        else if (leftLCA != null)
        {
            return leftLCA;
        }
        else if (rightLCA != null)
        {
            return rightLCA;
        }
        return null;
    }


Complexity: O(n)

Amazon Question: Set inorder successor of each node of Binary Tree

Solution:
1. Do reverse inorder traversal.
2. Set inorder successor to the previous node.

Source Code:
// Given node structure -

struct Node
{
int data;
Node* left;
Node* right;
Node* inorderSuccessor;
};


void BSTree::fillInorderSuccessor(Node* node, Node*& prev)
{
if(node)
{
fillInorderSuccessor(node->right, prev);
node->inorderSuccessor = prev;
prev = node;
fillInorderSuccessor(node->left, prev);
}
}

Amazon Question: Find number of vertical lines that can cover whole nodes of Binary Tree

Solution:

1. Do a preorder traversal.
2. Initialize count to 0.
3. Whenever encounter a left node increase count by 1.
4. Whenever encounter a right node decrease count by 1.
5. Return maxCount - minCount + 1.

Source Code:

int BTree::findVerticalLinesToCut(Node* node, int count)
{
static int max = 0, min = 0;
if(node)
{
max = max < count? count : max;
min = min > count ? count : min;

if(node->left)
{
findVerticalLinesToCut(node->left, count+1);
}
if(node->right)
{
findVerticalLinesToCut(node->right, count-1);
}
}
return max - min + 1;
}

Monday, October 3, 2011

Find the maximum sum of sub array within an array.

Problem: Given an integer array nums, find the subarray with the largest sum, and return its sum.

Example:
Input: nums = [-2,1,-3,4,-1,2,1,-5,4]
Output: 6
Explanation: The subarray [4,-1,2,1] has the largest sum 6.
Input: nums = [1]
Output: 1
Explanation: The subarray [1] has the largest sum 1.
Input: nums = [5,4,-1,7,8]
Output: 23
Explanation: The subarray [5,4,-1,7,8] has the largest sum 23.

Approach: This is simple Kadane's Algorithm. Just look at the implementation to understand the approach.


Implementation in C#:

    public int MaxSubArray(int[] nums)
    {
        int length = nums?.Length ?? 0;
        if (length == 0)
        {
            return int.MinValue;
        }
        int max = int.MinValue;
        int currSum = 0;
        int maxSum = int.MinValue;
        for (int i = 0; i < length; ++i)
        {
            if (max < nums[i])
            {
                max = nums[i];
            }
            currSum += nums[i];
            if (currSum < 0)
            {
                currSum = 0;
            }
            else
            {
                maxSum = Math.Max(currSum, maxSum);
            }
        }
        return max < 0 ? max : maxSum;
    }


Complexity: O(n)

[GFG][Amazon] Find the missing and repeating number

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

Example:

Input: arr[] = {3, 1, 3}
Output: Missing = 2, Repeating = 3
Explanation: In the array, 2 is missing and 3 occurs twice 

Input: arr[] = {4, 3, 6, 2, 1, 1}
Output: Missing = 5, Repeating = 1



Approach: We are going to use xor here.


Implementation in C++:

vector<int> findTwoElement(vector<int> arr, int n)
{
        // code here
        int xor1 = arr[0];
        for (int i = 1; i < n; ++i)
        {
            xor1 ^= arr[i];
        }
        
        for (int i = 1; i <= n; ++i)
        {
            xor1 ^= i;
        }
        
        int setBit = xor1 & ~(xor1 - 1);
        int x = 0, y = 0;
        for (int i = 0; i < n; ++i)
        {
            if (arr[i] & setBit != 0)
            {
                x ^= arr[i];
            }
            else
            {
                y ^= arr[i];
            }
        }
        for (int i = 1; i <= n; ++i)
        {
            if (i & setBit != 0)
            {
                x ^= i;
            }
            else
            {
                y ^= i;
            }   
        }
        vector<int> result;
        result.push_back(x);
        result.push_back(y);
        return result;
    }


Complexity: O(n)

Saturday, October 1, 2011

[Amazon] Sort array which contains only 0, 1 or 2 in O(n)

Problem: Sort an array which contains only 0, 1 or 2. The time complexity should not be more than O(n).

Example:
Input: arr = [0, 1, 2, 0, 1, 1, 2]
Output: [0, 0, 1, 1, 1, 2, 2]


Approach: We will use three pointer approach here.


Implementation in C#:

    public void SortColors(int[] nums)
    {
        int length = nums?.Length ?? 0;
        if (length <= 1)
        {
            return;
        }
        int low = 0;
        int high = length - 1;
        for (int mid = 0; mid <= high;)
        {
            Console.WriteLine($"{mid}: {nums[mid]}");
            switch(nums[mid])
            {
                case 0: this.Swap(nums, low++, mid++);
                    break;
                case 1: mid++;
                    break;
                case 2: this.Swap(nums, mid, high--);
                    break;
            }
        }
    }

    private void Swap(int[] nums, int i, int j)
    {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }


Complexity: O(n)

Friday, September 16, 2011

Reverse a Linked List using one pointer.

void reverse(node* temp)
{
     if(temp->next)
     {
        reverse(temp->next);
        temp->next->next = temp;
        temp->next = NULL;
     }
    else
            head = temp;
}


Note: It is not actually one pointer as we are using recursion.

Given pointers to two Single Linked List find out if they joined in Y shape and also at which node they are joined.

Solution:

To check whether they joined in Y shape or not --

if ( End(List1) = = End(List2) )
    // Merged

To find the node --

count1 = Size ( List1 ) ;
count2 = Size ( List2 ) ;

longList = List1 ;
smallList = List2 ;
count2 > count1 && ( swap( longList, smallList ) ) ;

for ( int i = 0; i < abs(count1 - count2); longList = longList -> next, ++i ) ;

while(longList !- null && longList != smallList )
{
      longList  =  longList -> next ;
      smallList = smallList -> next ;
}

return longList ;

In C# -

        public LinkedListNode GetIntersectionNode(LinkedList list2)
        {
            int count1 = this.Count();
            int count2 = list2.Count();

            LinkedListNode longListNode, shortListNode;
            if (count1 >= count2)
            {
                longListNode = this.Head;
                shortListNode = list2.Head;
            }
            else
            {
                longListNode = list2.Head;
                shortListNode = this.Head;
            }

            for (int i = 0; i < Math.Abs(count1 - count2); longListNode = longListNode.Next, ++i);

            while(longListNode != null && longListNode != shortListNode)
            {
                longListNode = longListNode.Next;
                shortListNode = shortListNode.Next;
            }

            return longListNode;
        }

Remove duplicate characters from a string in O(n).

Solution:
void remove(char *str )
{
    bool hash[256] = {0} ;
    for(int i =0, j=0 ; str[i] != '\0'; ++i)
          hash[str[i]] || (hash[str[i]] = true, str[j++] = str[i]);
    str[j] = '\0';
}

Delete a node from singly linked list when only pointer to node to be deleted is given in O(1).

Solution:
Say node to be deleted is toDelete.
copy ( toDelete->next->element, toDelete->element);
remove( toDelete->next );

* We are not really deleting the node but we are achieving what we want to do ;)
* Problem in this approach when toDelete is the last node, Solution is circular linked list or a temporary tail node

Design a Data Structure which supports push, pop and findMin operation in O(1).

Solution:

Extra Space:

Use two stack say stack1 and stack2. stack2 is used to keep track of Minimum number in the list at each step.

push( n ):    stack1.push(n);
                 stack2.push( Min( n, stack2.top( ) ) );

pop( ):        stack1.pop( );
                 stack2.pop( );

findMin( ):  stack2.top( );

Adobe Question: Multiply two numbers using bitwise operators

Solution:

A =            101
B =              10
                  -------
                    000
                  101x             x here denotes a left shift by 1 bit.
                  -------
Result =      1010

The magic is to check for the last bit of B. If the last bit is 1, then add ‘A’ to result else do nothing. And after every check right shift ‘B’ by 1 bit and left shift ‘A’ by 1 bit.

To add two numbers using bitwise, you need to implement the full adder where you calculate sum and carry as below:
Sum = A xor B (A ^ B)
Carry = A and B (A & B)


Source:
int bitwiseMultiply(int a, int b)
{
int result = 0;
while ( b != 0)
{
if ( b & 1)
{
result = sum( a, result);
}
a = a << 1; b = b >> 1;
}
return result;
}

int sum (int a, int b)
{
int sum = 0;
int carry = 0;
while ( a )
{
carry = a & b;
sum = a ^ b;
carry = carry << 1;
a = carry;
}
return sum;
}

Thursday, September 8, 2011

Amazon Question: An array is containing only 0 and 1. Find out the largest subarray in which number of 1s are equal to number of 0s.

Solution: 
  1. Replace 0 with -1.
  2. Find the cumulative sum at each index.
  3. In the cumulative sum array if at some index sum is 0 that means from index 0 to current index number of 0 and 1 are same.
  4. If there are duplicates in the cumulative sum array that means the cumulative sum is 0 in between so there are equal number of 0s and 1s.
  5. Just find out the longest one and return it.

Source Code:

string longestSubStrWithEqual0and1(int *arr, int size)
{
    string strResult = "";
    map<int, int> mapIntToInt;
    if(arr == NULL || size == 0)
        return strResult;
    int i=1;
    int* cumSumArr = new int[size];
    if(arr[0] == 1)
        cumSumArr[0] = 1;
    else if(arr[0] == 0)
        cumSumArr[0] = -1;
    else
        return strResult; // Error as there is interger other than 0 and 1 in array
    for(; i<size; ++i)
    {
        if(arr[i] == 0)
            cumSumArr[i] = cumSumArr[i-1] + (-1);
        else if(arr[i] == 1)
            cumSumArr[i] = cumSumArr[i-1] + 1;
        else
            return strResult; // Error as there is interger other than 0 and 1 in array
    }
   
    int maxLen =0;
    int startIndex = 0;
    int endIndex = 0;
    for(i=0; i<size; ++i)
    {
        if(mapIntToInt.find(cumSumArr[i]) == mapIntToInt.end())
        {
            mapIntToInt[cumSumArr[i]] = i;
        }
        else
        {
            int len = i - mapIntToInt[cumSumArr[i]];
            if(maxLen < len)
            {
                maxLen = len;
                startIndex = mapIntToInt[cumSumArr[i]] + 1;
                endIndex = i;
            }
        }
        if(cumSumArr[i] == 0)
        {
            maxLen = i + 1;
            startIndex = 0;
            endIndex = i;
        }
       
    }
    if(maxLen > 0)
    {
        for(i = startIndex; i <= endIndex; ++i)
        {
            strResult += ('0' + arr[i]);         }
    }
    delete [] cumSumArr;
    return strResult;
}

Saturday, September 3, 2011

Salesforce Question: Spiral Order Traversal of Binary Tree


void BinaryTree::SpiralTraversal(Node* root)
{
    stack<Node*> stack1, stack2;
    stack1.push(root);
    while(!stack1.empty() || !stack2.empty())
    {
        while(!stack1.empty())
        {
            Node* node1 = stack1.top();
            stack1.pop();
            cout<<node1->data<<'\n';
            if(node1->right)
                stack2.push(node1->right);
            if(node1->left)
                stack2.push(node1->left);
        }
        while(!stack2.empty())
        {
            Node* node2 = stack2.top();
            stack2.pop();
            cout<<node2->data<<'\n';
            if(node2->left)
                stack1.push(node2->left);
            if(node2->right)
                stack1.push(node2->right);
        }
    }
}

Amazon Question: Design LRU Cache

It was told that cache will have a key, value pair(int, int).

Solution is to take hash with key as cache key and value is Node where Node is the address of the node in the linked list which contains the same key. Linked list node contains cache key and cache value.


Insert Operation --
  1. Make a node "Node" with key and value and put that node at the end of linked list. 
  2. if count of nodes are more than cache size then remove head node from linked list , also remove hash[head->key].
  3. Update hash as hash[Node->key] = Node

Get Operation --
  1. Get operation will return the cache value of given cache key. Also now it will make this key is the most recently used one.
  2. Get the Node by hash[key] and move that Node at the end of linked list.
  3. Return hash[key]->value.   

Implementation in C#:

    public class LRUCache
    {
        public LRUCache(int capacity)
        {
            this.currentCount = 0;
            this.cacheCapacity = capacity;
            this.list = new LinkedList<KeyValuePair<int, int>>();
            this.hash = new Dictionary<int, LinkedListNode<KeyValuePair<int, int>>>();
        }

        public int Get(int key)
        {
            if (hash.ContainsKey(key))
            {
                list.Remove(hash[key]);
                list.AddLast(hash[key]);
                return hash[key].Value.Value;
            }
            return -1;
        }

        public void Put(int key, int value)
        {
            if (hash.ContainsKey(key))
            {
                hash[key].Value = new KeyValuePair<int, int>(key, value);
                list.Remove(hash[key]);
                list.AddLast(hash[key]);
            }
            else
            {
                if (currentCount + 1 > cacheCapacity)
                {
                    LinkedListNode<KeyValuePair<int, int>> linkedListNode = list.First;
                    list.RemoveFirst();
                    hash.Remove(linkedListNode.Value.Key);
                }
                else
                {
                    ++currentCount;
                }

                LinkedListNode<KeyValuePair<int, int>> newNode = new LinkedListNode<KeyValuePair<int, int>>(new KeyValuePair<int, int>(key, value));
                list.AddLast(newNode);
                hash.Add(key, newNode);
            }
        }

        Dictionary<int, LinkedListNode<KeyValuePair<int, int>>> hash;
        LinkedList<KeyValuePair<int, int>> list;
        private int cacheCapacity;
        private int currentCount;
    }

Thursday, August 4, 2011

Salesforce Question: Given two arrays A and B, find out elments of B which are not in A

Hash all the elements of A.
if B[i] is not in hash add into the result. 0<=i<sizeof(B)