Thursday, September 10, 2015

Next Greater Element

Problem Statement:-
Given an array, print the Next Greater Element (NGE) for every element. The Next greater Element for an element x is the first greater element on the right side of x in array. Elements for which no greater element exist, consider next greater element as -1.
For the input array [4, 5, 2, 25}, the next greater elements for each element are as follows.
Element       NGE
   4      -->   5
   5      -->   25
   2      -->   25
   25     -->   -1

Solution in JAVA int time complexity O(n) 
import java.io.*;
import java.util.*;
class nextGreater
{
    public static void nextGreat( int a[], int len)
    {
        int element, next;
        Stack mystack = new Stack();
        for(int i=0; i<len; i++)
        {   
            next = a[i];
            while(!mystack.empty())
            {
                element=(int)mystack.pop();
                if(element > next)
                {
                    //push back the element 
                    mystack.push(element);
                    break;
                }
                else
                {
                    System.out.println( element +"-------->"+next);
                }
            }
            mystack.push(a[i]);
        }
        while(!mystack.empty())
        {
            element = (int)mystack.pop();
            System.out.println( element +"-------->"+"-1");
        }
        return;
    }
    public static void main(String []args)
    {
        int a[] = {1,2,23,3,4,205,25,1,2,100,2,3,4,200,105};
        nextGreat(a,a.length);
     }
}

Thursday, September 3, 2015

Minimum Initial Points to Reach Destination


Given a grid with each cell consisting of positive, negative or no points i.e, zero points. We can move across a cell only if we have positive points ( > 0 ). Whenever we pass through a cell, points in that cell are added to our overall points. We need to find minimum initial points to reach cell (m-1, n-1) from (0, 0).


Constraints :
  • From a cell (i, j) we can move to (i+1, j) or (i, j+1).
  • We cannot move from (i, j) if your overall points at (i, j) is <= 0.
  • We have to reach at (n-1, m-1) with minimum positive points i.e., > 0
Example

Input: points[m][n] = { {-2, -3,   3}, 
                        {-5, -10,  1}, 
                        {10,  30, -5} 
                      };
Output: 7
Explanation: 
7 is the minimum value to reach destination with 
positive throughout the path. Below is the path.

(0,0) -> (0,1) -> (0,2) -> (1, 2) -> (2, 2)

We start from (0, 0) with 7, we reach(0, 1) 
with 5, (0, 2) with 2, (1, 2) with 5, (2, 2)
with and finally we have 1 point (we needed 
greater than 0 points at the end). 

pasting the code below, please let me know if you found any bug in it.
import java.io.*;

class minInitialDP
{
    public static int max(int x, int y)
    {
        return (x>y?x:y);
    }

    public static int min(int x, int y)
    {
        return (x<y?x:y);
    }

    public static void main(String []args)
    {
        int points[][] = { {-2, -3,   3}, 
                        {-5, -10,  1}, 
                        {10,  30, -5} 
                      };

        int DP [][] = new int[3][3];

        // main code goes here 

        for(int i=0; i<3; i++)
        {
            for(int j=0; j<3; j++)
            {
                if (i==0 && j==0)
                {
                    DP[i][j] = 0;
                    continue;
                }

                if( i==0 )
                {
                    if(points[i][j-1] < 0)
                    {
                        DP[i][j] = -points[i][j-1]+DP[i][j-1]+1;       
                    }
                    else
                    {
                        DP[i][j] = DP[i][j-1];
                    }
                    continue;
                }

                if(j==0)
                {
                    if(points[i-1][j] < 0)
                        DP[i][j] = -points[i-1][j]+DP[i-1][j]+1;
                    else
                        DP[i][j] = DP[i-1][j];
                    continue;
                }

                int pi, pj;

                if(points[i][j-1] < 0)
                    pi = -points[i][j-1]+DP[i][j-1]+1;
                else
                    pi =  DP[i][j-1];

                if(points[i-1][j] < 0)
                    pj = -points[i-1][j]+DP[i-1][j]+1;
                else
                    pj = DP[i-1][j];

                DP[i][j] = min(pi, pj);
            }
        }

        for(int i=0; i<3; i++)
        {
            for(int j =0; j<3; j++)
                 System.out.print(DP[i][j] + " ");
            System.out.println("\n");
        }
    }

}

Saturday, August 22, 2015

Find length of the longest consecutive path from a given starting character

Given a matrix of characters. Find length of the longest path from a given character, such that all characters in the path are consecutive to each other, i.e., every character in path is next to previous in alphabetical order. It is allowed to move in all 8 directions from a cell.

example:

for mat[][]={{a,c,d},
                     {h,b,e},
                     {i,g,f}} 
and input character 'e' o/p will be 5

At first this problem is looking easy (Indeed this is) by simply finding the next character via doing a 8 way recursion, this is doable this way but we can do it more efficiently by using dynamic programing, there can be some subproblem while we are searching for a path so we will store that paths in our dp matrix and will use it in between.

simple solution in java 

class SearchPath
{
    public static final int R=3;
    public static final int C=3;

    // matrix for tracking purpose 
    public static boolean [][] visited;
    
    //input matrix
    public static char [][] mat ={ {'a','c','d'},{ 'h','b','a'},{ 'i','g','f'}};
    
    // just storing all 8 position for iterative recurs 
    public static int [] x = {1,0,1,1,-1,-1,0,-1};
    public static int [] y = {0,1,1,-1,1,-1,-1,0};
    
    //dp storage
    public static int [][]dp;
    
    public static int max(int a, int b)
    {
        return(a>b?a:b);
    } 

    //will check if and i,j pair in matrix valid or not
    public static boolean isValid(int i, int j)
    {
        if(i<0 || j<0 || i>=R || j >=C)
            return false;
        else
            return true;
    }
    
    public static int getpath_util(char m, int r, int c)
    {
        if(!isValid(r,c) || visited[r][c] ||  m+1 != mat[r][c])
            return 0;
        if(dp[r][c]!= -1)
        {
            return dp[r][c];
        }
        
        // make this visited so in subsequent call it will not be taken into account
        
        visited[r][c] = true;
        int ans=0;
        for(int k=0; k<8; k++)
        {
            ans= max(ans, 1+getpath_util(mat[r][c], x[k]+r, y[k]+c));
        }  
        
        // unset this
        visited [r][c] = false;
        
        return dp[r][c] = ans;
        
    }
    public static void getpath(char m)
    {
        int ans=0;
        for(int i=0; i<R; i++)
        {
            for(int k=0; k<C;k++)
            {
                if(mat[i][k] == m)
                {
                    for(int j=0; j<8; j++)
                    {   
                        ans = max(ans, 1+getpath_util(m, i+x[j], k+y[j]));
                    }       
                }
            }
        }   
        System.out.println(ans);
    }
    public static void main(String[]args)
    { 
        visited  = new boolean[R][C];
        dp = new int [R][C];
        for(int i=0; i<R;i++)
            for(int k=0; k<C; k++)
                dp[i][k]=-1;
        for(int i=0; i<R;i++)
            for(int k=0; k<C; k++)
                visited[i][k]=false;
        getpath('a');
        getpath('e');
        getpath('b');
        getpath('f'); 
    }

}


Source:- gfg

Thursday, August 20, 2015

Merge two sorted linked list (Recursive Approach)


Merge is one of those nice recursive problems where the recursive solution code is much cleaner than the iterative code

Node *Merge(Node * head1, Node *head2)
{
        // Base conditions

       if(! head1 || !head2)
       {
              if(!head1)
                   return head2;
              else
                   return head1;
     
        }
        else
        {

                 if(Node1.data <= Node2.data)
                 {

                        Node1.next = Merge(Node1.next, Node2)
                        return Node1;

                 }
                 else
                 {
       
                       Node2.next= Merge(Node1, Node2.next);
                       return Node2;
                 }
        }

}

Tuesday, August 18, 2015

[Uber][LeetCode] Trapping Rain Water

Problem: Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining.

Example:

Input: height = [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
Explanation: The above elevation map (black section) is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped.
Input: height = [4,2,0,3,2,5]
Output: 9

Approach: Basically if we see the problem closely, we can easily figure out that the trapped water amount at any bar 'i' is as follows:

water(i) = Min (max height among all the bar in left of i, max height among all the bars in right of i ) - height(i)

We just need the sum of all of these amount to get the answer. We can achieve it using brute force approach but let's try to do better:

we can pre calculate the max height from left for every i and store in an array say leftMax and we can do the same from the right and store it in the array say rightMax. Now the calculation is something like this:
  • FOR i = 1 TO n
    • water += ( Min(leftMax[i], rightMax[i]) - height[i])

This approach will solve the problem in linear time but if you see it is taking extra space. Let's try to reduce it. The intuition is if till leftMax is greater than rightMax, we just calculate according to rightMax only right? (see above, we take the min only). Same thing we can say about when rightMax is greater than leftMax.

Now we can use two pointer approach one from left (index = 0) and one from right(index = n - 1) and can follow the following steps:
  • WHILE left < right
    • IF height[left] < height[right]
      • IF height[left] > leftMax //. can't trap water 
        • leftMax = height[left]
      • ELSE
        • water += leftMax - height[left]
      • ++left;
    • ELSE
      • // same for right
      • --right

Implementation in C#:

Approach 1:

    public int Trap(int[] height) 
    {
        int length = height?.Length ?? 0;
        if (length <= 1)
        {
            return 0;
        }
        int[] leftMax = new int[length];
        leftMax[0] = height[0];
        for (int i = 1; i < length; ++i)
        {
            leftMax[i] = Math.Max(leftMax[i - 1], height[i]);
        }
        int[] rightMax = new int[length];
        rightMax[length - 1] = height[length - 1];
        for (int i = length - 2; i >=0; --i)
        {
            rightMax[i] = Math.Max(rightMax[i + 1], height[i]);
        }
        int sum = 0;
        for (int i = 1; i < length - 1; ++i)
        {
            sum += (Math.Min(leftMax[i], rightMax[i]) - height[i]);
        }
        return sum;
    }


Approach 2:

    public int Trap(int[] height) 
    {
        int length = height?.Length ?? 0;
        
        if (length <= 1)
        {
            return 0;
        }
        
        int left = 0, right = length - 1;
        
        int leftMax = 0, rightMax = 0, sum = 0;
        
        while (left < right)
        {
            if(height[left] < height[right])
            {
                if (height[left] > leftMax)
                {
                    leftMax = height[left];
                }
                else
                {
                    sum += (leftMax - height[left]);
                }
                ++left;
            }
            else
            {
                if (height[right] > rightMax)
                {
                    rightMax = height[right];
                }
                else
                {
                    sum += (rightMax - height[right]);
                }
                --right;
            }
        }
        return sum;
    }


Complexity: O(n)

Tuesday, July 21, 2015

Insertion Sort

The idea behind the insertion sort is to loop over positions in the array, starting with index 1. Each element at the given index needs to be inserted  into the correct place in the array.

Although it is one of the elementary sorting algorithms with O(n2) worst-case time, insertion sort is the algorithm of choice either when the data is nearly sorted (because it is adaptive) or when the problem size is small (because it has low overhead).

For these reasons, and because it is also stable, insertion sort is often used as the recursive base case (when the problem size is small) for higher overhead divide-and-conquer sorting algorithms, such as merge sort or quick sort.

Implementation:

void insertionSort(int *arr, int len)
{
if(arr == NULL || len <= 1)
return;

for(int i = 1; i < len; ++i)
{
int key = arr[i];
int j = i  - 1;
for(; j >= 0 && arr[j] > key; --j)
arr[j+1] = arr[j];

arr[j + 1] = key;
}
}

Complexity: O(n2)

Monday, July 13, 2015

Size of binary tree

Problem: Write a method which returns the number of nodes present in the given binary tree.

Solution: Do any traversal and instead of printing the node, count the number of nodes. I am using post order traversal here.

Implementation:

//Public Interface
int BSTree::size()
{
if(!root)
return 0;
return size(root);
}

//Actual Implementation
int BSTree::size(BSTree::Node *node)
{
if(!node)
return 0;
int ls = size(node->left);
int rs = size(node->right);

return ls + rs + 1;

Complexity: O(n)

Thursday, July 9, 2015

Longest Increasing Subsequence

A sequence of numbers a1, a2,..., an, a sub-sequence is ai1, ai2, ... , aik where 1 <= i1 < i2 < ... < ik <= n and an increasing sub-sequence is one in which the numbers are getting strictly larger. The task is to find the increasing sub-sequence of greatest length.

Example: The longest increasing sub-sequence of 5, 2, 8, 6, 3, 6, 9, 7 is 2, 3, 6, 9:


Solution: Create a graph of all permissible transitions: establish a node i for each element ai, and add directed edges (i, j) whenever it is possible for ai and aj to be consecutive elements in an increasing sub-sequence,that is, whenever i < j and ai < aj.


Note that this graph G = (V,E) is a dag, since all edges (i, j) have i < j, and there is a one-to-one correspondence between increasing sub-sequences and paths in this dag. Therefore, our goal is simply to find the longest path in the dag. Here is the algorithm:


Implementation:

int LIS(int arr[], int len)
{
int *L = new int[len];

for(int i = 0; i < len; ++i)
L[i] = 1;

for(int j = 1; j < len; ++j)
{
for(int i = 0; i < j; ++i)
{
if((arr[j] > arr[i]) && (L[j] < L[i] + 1))
L[j] = L[i] + 1;
}
}

int max = 0;
for(int i = 0; i < len; ++i)
{
if(max < L[i])
max = L[i];
}

delete [] L;
return max;
}

Complexity: O(n2)

Monday, July 6, 2015

OLA Question: Modify Boolean matrix

Problem: Given a Boolean matrix , modify it such that if a matrix cell mat[i][j] is true then make all the cells of ith row and jth column as true.

Solution: Following are the steps -
  1. Traverse the first row and set a variable firstRowFlag to indicate whether all the cells in first row should be set to true or not.
  2. Similarly traverse the first column and set a variable firstColFlag to indicate whether all the cells in first column should be set to true or not.
  3. Now set all the cells in first row and column as false.
  4. Traverse the input matrix and see if mat[i][j] is true, then set mat[0][j] and mat[i][0] as true.
  5. Traverse the input matrix and for each entry mat[i][j], check if either mat[0][j] or mat[i][0] is true, then set mat[i][j] to true.
  6. Now, using firstRowFlag and firstColFlag, update first row and first column if needed.

Implementation:

void modifyBoolMatrix(bool **mat, int M, int N)
{
bool firstRowFlag = false, firstColFlag = false;
for(int i = 0; i < N; ++i)
{
if(mat[0][i])
{
mat[0][i] = false;
firstRowFlag = true;
}
}

for(int i = 0; i < M; ++i)
{
if(mat[i][0])
{
mat[i][0] = false;
firstColFlag = true;
}
}

for(int i = 1; i < M; ++i)
{
for(int j = 1; j < N; ++j)
{
if(mat[i][j])
{
mat[0][j] = true;
mat[i][0] = true;
}
}
}

for(int i = 1; i < M; ++i)
{
for(int j = 1; j < N; ++j)
{
if(mat[0][j] || mat[i][0])
mat[i][j] = true;
}
}

if(firstRowFlag)
{
for(int i = 0; i < N; ++i)
mat[0][i] = true;
}

if(firstColFlag)
{
for(int i = 0; i < M; ++i)
mat[i][0] = true;
}
}

Complexity: O(M * N)

Amazon Question: Add two numbers represented by linked lists

Problem: Given two numbers represented by two linked lists, write a method that returns linked list representing the addition of two input numbers.

Solution: No need to explain. Can be easily understood by the implementation.

Implementation:

//All of these methods are friends to List class

void addAtFront(List::ListNode*& head, int num)
{
List::ListNode* newNode = new List::ListNode(num, head);
head = newNode;
}

void addCarry(List::ListNode* node1, List::ListNode* node2, int& carry, List::ListNode *&result)
{
if(node1 != node2)
{
addCarry(node1->next, node2, carry, result);
int sum = node1->data + carry;
carry = sum/10;
sum = sum % 10;
addAtFront(result, sum);
}
}

List::ListNode* addSameLenNum(List::ListNode* node1, List::ListNode* node2, int& carry)
{
if(!node1)
return NULL;
List::ListNode *node = new List::ListNode();
node->next = addSameLenNum(node1->next, node2->next, carry);
int sum = node1->data + node2->data + carry;
carry = sum / 10;
node->data = sum % 10;
return node;
}

List* addNum(List l1, List l2)
{
if(!l1.head)
{
return new List(l2);
}
if(!l2.head)
{
return new List(l1);
}
 List* result = new List()
List::ListNode *head1 = l1.head, *head2 = l2.head;
int len1 = l1.len, len2 = l2.len;
int carry = 0;
if(len1 == len2)
result->head = addSameLenNum(l1.head, l2.head, carry);
else
{
if(len1 < len2)
{
head1 = l2.head;
head2 = l1.head;
}
int diff = std::abs(len1 - len2);
List::ListNode* curr = head1;
for(int i = 0; i < diff; ++i, curr=curr->next);
result->head = addSameLenNum(curr, head2, carry);
addCarry(head1, curr, carry, result->head);
}

if(carry)
addAtFront(result->head, carry);

return result;
}

Complexity: O(n)

Thursday, July 2, 2015

Width of a binary tree

Problem: Given a binary tree, write a method to get the width of the given binary tree. Width of a tree is maximum of widths of all levels in the tree.

Solution: Use level order traversal.

Implementation:

int BSTree::getWidth()
{
int maxW = -1;
if(!root)
return maxW;
std::queue<Node*> q[2];
bool turn = 0;
q[turn].push(root);
while(!q[turn].empty())
{
int currW = q[turn].size();
if(maxW < currW)
maxW = currW;
while(!q[turn].empty())
{
Node *temp = q[turn].front();
if(temp->left)
q[!turn].push(temp->left);
if(temp->right)
q[!turn].push(temp->right);
q[turn].pop();
}

turn = !turn;
}

return maxW;
}

Complexity: O(n)

Kth min in BSTree

Problem: Write a method which returns the kth minimum element in a given Binary Search Tree.

Solution: Use inorder traversal.

Implementation:

        //Public interface
        public int KthSmallest(int k)
        {
            if (this.Root == null || k <= 0)
            {
                return 0;
            }
            int result;
            this.KthSmallest(this.Root, ref k, out result);
            return result;
        }

        //Actual Implementation
        private void KthSmallest(BinaryTreeNode node, ref int k, out int result)
        {
            if (node == null)
            {
                result = -1;
                return;
            }

            this.KthSmallest(node.LeftNode, ref k, out result);

            if (--k == 0)
            {
                result = node.Value;
            }
            else if (k > 0)
            {
                this.KthSmallest(node.RightNode, ref k, out result);
            }
        }

Complexity: O(k)

Kth max in BSTree

Problem: Write a method which returns the kth maximum element in a given Binary Search Tree.

Solution: Use reverse inorder traversal.

Implementation:

//Public interface
int BSTree::kthMax(int k)
{
if(!root || k <= 0)
return -1;
return kthMax(root, k);
}

//Actual implementation
int BSTree::kthMax(BSTree::Node *node, int& k)
{
static int result = -1;
if(node)
{
kthMax(node->right, k);
if(--k == 0)
result = node->data;
if(k > 0)
return kthMax(node->left, k);
}
else if(k > 0)
result = -1;
return result;
}

Complexity: O(n)

Tuesday, June 30, 2015

Nearest smaller numbers on left side

Problem: Given an array of integers, find the nearest smaller number for every integer on its left side.

Solution: Use stack.

Implementation:

void printNearestSmaller(int arr[], int len)
{
if(len <= 0)
return;

std::stack<int> st;
for(int i = 0; i < len; ++i)
{
while(!st.empty() && st.top() >= arr[i])
st.pop();

if(st.empty())
std::cout<<"-\t";
else
std::cout<<st.top()<<'\t';
st.push(arr[i]);
}
std::cout<<std::endl;
}

Complexity: O(n)

Thursday, June 18, 2015

Microsoft Question: Sort an array such that all odd numbers are in left side and sorted in increasing order where all even numbers are sorted in decreasing order and come after the odd numbers.

Problem: Sort an array such that all odd numbers are in left side and sorted in increasing order where all even numbers are sorted in decreasing order and come after the odd numbers.

Solution: Segregate the odd number and even numbers and then sort these sub arrays separately in ascending and descending order.

Implementation:

void sortOddEven(int arr[], int len)
{
int i = 0, j = len - 1;
while(i < j)
{
while((arr[i] % 2 != 0) && (i < j))
++i;
while((arr[j] % 2 == 0) && (i < j))
--j;
if(i < j)
{
std::swap(arr[i], arr[j]);
++i;
--j;
}
}
std::sort(arr, arr + i);
if(i < len)
std::sort(arr + i, arr + len, std::greater<int>());
}

Complexity: O(nlogn)