Sunday 19 July 2015

Find maximum sum subarray


Question: Given an array of integers(positive/negative) find a sub-array such that it gives max sum.  

Solution(s):
Method 1: Using divide and conquer: Divide the given array in 2 sub-arrays from middle and find maximum sum in those sub-arrays.
case 1 : maximum sum is in left subarry
case 2 : maximum sum is in right subarry
case 3 : maximum sum may exist at the crossing point including both the sub-arrays Find the maximum from all these 3 cases that will give the maximum sum sub-array.

Method 2: Using Kadane's algorithm In this algorithm we scan the array and keep track of elements and based on the condition that either adding the current value will increment variable or not, we update the variables. Following program implements divide and conquer approach and Kadane's algorithm.
/**
 * @author Vikky.Agrawal
 * 
 */
public class MaxSumSubArray {

 int arr[];

 MaxSumSubArray() {
      arr = new int[] { -2, 1, -3, 4, -1, 2, 1, -5, 4 };
     //arr = new int[] { -2, -1, -3, -4, -1, -2, -1, -5, -4 };
 }

 public static void main(String[] args) {
  new MaxSumSubArray().operate();

 }

 public void operate() {
  System.out.println("Max sum is " + findMaxSum(arr, 0, arr.length - 1));
  System.out.println("Max sum using kadane's algo :"
    + findMaxSubArraySum(arr));
  System.out.println("Alternate kadane's :"+findMaxSumKadane(arr));
  
 }

 //Method 1: divide and conquer  
 public int findMaxSum(int arr[], int low, int high) {

  if (low == high) {
   return arr[low];
  }

  int mid = (low + high) / 2;
  return maxOfThree(findMaxSum(arr, low, mid),
    findMaxSum(arr, mid + 1, high),
    maxCrossSum(arr, low, mid, high));

 } 

//case 3: check whether max sum exist including crossing point. public int maxCrossSum(int arr[], int low, int mid, int high) { int leftSum = Integer.MIN_VALUE; int rightSum = Integer.MIN_VALUE; int sum = 0; for (int i = mid; i >= low; i--) { sum = sum + arr[i]; if (sum > leftSum) { leftSum = sum; } } sum = 0; for (int j = mid + 1; j <= high; j++) { sum += arr[j]; if (sum > rightSum) { rightSum = sum; } } return leftSum + rightSum; } /** * Method 2: Using Kadane's algorithm * will return negative if all elements are negative * Time complexity : O(n) **/
 public int findMaxSubArraySum(int arr[]) { int max_ending_here = arr[0]; int max_so_far = arr[0]; int begin = 0; int end = 0; int temp = 0; for (int i = 1; i < arr.length; i++) { if (max_ending_here < arr[i]) { max_ending_here = arr[i]; temp = i; } else { max_ending_here += arr[i]; } if (max_ending_here >= max_so_far) { max_so_far = max_ending_here; begin = temp; end = i; } } System.out.println("Largest subarry start index :" + begin + " end index : " + end); return max_so_far; } //Another approach using Kadane's algorithm public int findMaxSumKadane(int arr[]){ int length=arr.length; if(length==0){ return Integer.MIN_VALUE; } //This will help with negative numbers. int max_ending_here =arr[0], max_so_far = arr[0]; for(int j=1; j<length; j++){ max_ending_here=maxOfTwo(max_ending_here+arr[j],arr[j]); max_so_far= maxOfTwo(max_so_far, max_ending_here); } return max_so_far; } // Helper functions public int maxOfTwo(int a, int b) { return a > b ? a : b; } public int maxOfThree(int a, int b, int c) { return maxOfTwo(maxOfTwo(a, b), c); } }
Complexity Analysis
For method 1(divide and conquer): it resembles to Master theorem case 2 hence time taken will be T(n)=2T(n/2)+O(n) = O(n logn)
For method 2: Kadane's algorithm makes only a single pass of the whole array hence time complexity will be O(n) which is linear and significant improvement than divide and conquer approach.

Saturday 18 July 2015

Reverse a stack

Given a stack, following program recursively reverses it:
/**
 * @author vikky.agrawal
 * Stack reversal
 */

public class StackImpl {

 Node top =null; 
 
 public static void main(String[] arg){ 
  
  StackImpl stack=new StackImpl();
  stack.stackOperations();
 }
 
 
 public void stackOperations(){
  

  for (int i = 1; i < 10; i++) {
   push((int) (Math.random() * 100));
  }
  
  printStack();
  
  top=this.reverseStack(top);
  System.out.println("Stack after reverse");
  printStack();
  
  
 }
 
 
 
 public Node reverseStack(Node tos){
  
  
  ///base case
  if(tos==null || tos.getLink()==null){
   return tos;
  }  
  
  //point temp to last node and then set link recursively.
  Node temp=reverseStack(tos.getLink());
  
  tos.getLink().setLink(tos);  //a->b->c->null,set b's backward link a<-b<-c;  
                                             // and set b's forward link as null
  tos.setLink(null);
  
  return temp; //always last node, hence top of reversed Stack
 }

 
 /**
  * Helper functions for stack operations
  */
 
 public void push(int data){
  if(top==null){
   top=new Node(data);
  }else{
   Node temp=new Node(data);
   temp.setLink(top);
   top=temp;
  }
 }
 
 public int pop(){
  if(top==null){
   return -1;
  }else{
   Node temp=top;
   top=top.getLink();
   return temp.getData();
  }
 }
 
 public int peek(){
  if(top!=null){
   return top.getData();
  }else{
   return -1;
  }
 }
 
 
 public boolean isEmpty(){
  if(top==null)
   return true;
  return false;
 }
 
 
 public int size(){
  int size=0;
  Node temp=top;
  
  while(temp!=null){
   size++;
   temp=temp.getLink();
  }
  return size;
 }
 
 public void printStack(){
  Node temp=top;
  System.out.print("Top->\n");
  while(temp!=null){
   System.out.println(temp.getData()+"\n|");
   temp=temp.getLink();
  }
  System.out.println("/null");
 }
 
 /**
  * static inner class to be used for Stack Data Structure
  */
  static class Node{
   private int data;
   private Node link;    
      
      Node(){
            
      }
      
      Node(int data){
       //mergedList=new Node();
          this.setData(data);
          this.setLink(null);       
      }
      
      public int getData(){
          return this.data;
      }
        
      public Node getLink(){
          return this.link;
      }
      
      public void setData(int data){
          this.data=data;
      }       
      
      public void setLink(Node link){
          this.link=link;
      }  
 }
 
}

Find kth largest or smallest element in unsorted array

Question :Find Kth element(largest/smallest) in an unsorted array

Solution: Using pivot finding method of QuickSort we can find Kth element's position it will give Kth smallest element, to find Kth largest modify the program to find smallest from the end. Following program finds Kth largest in an un-sorterd array:
 
/**
 * @author Vikky.Agrawal
 *
 */
public class LargestK {

 int arr[];
 int length;
 
 LargestK(){
  arr=new int[]{16,17,18,4,12,9,5,1};
  this.length=arr.length;
 }
 
 /**
  * @param args
  */
 public static void main(String[] args) {
  new LargestK().operate();
 }
 
 
 public void operate(){
  int k=1;
  System.out.println(k+" th largest in array : "+findKthLargest(arr, 0, length-1, length-k));
  
 }
 
 
 //Using QuickSort's pivot finding method
 public int findKthLargest(int[] arr, int p, int q, int k) {

  if(p==q){
   if(k==p){
    return arr[p];
   }else{
    return -1;
   }
  } 
  
  else if (p < q) {
   int pivot = findPivot(arr, p, q);
   
   if (pivot == k)
    return arr[pivot];
   if (pivot > k) {
    return findKthLargest(arr, 0, pivot-1, k);
   } else {
    return findKthLargest(arr, pivot + 1, length-1, k);
   }
  }else{
   return -1;
  }
  
 }
 
 public int findPivot(int[] arr, int p, int r){
  
  int x=arr[r];
  int i=p-1; 
  
  for(int j=p ;j<r; j++){
   if(arr[j]<= x){
    i++;
    int temp=arr[i];
    arr[i]=arr[j];
    arr[j]=temp;
   }
  }  
  
  arr[r]=arr[i+1];
  arr[i+1]=x;
  return i+1;
 }
}


Complexity Analysis:
Time required to find pivot = O(n)
In average cases only half of the array will be searched(assuming pivot will divide the array in half), time required to divide will be T(n/2).
Hence total time to find Kth largest T(n) = T(n/2)+O(n) = O(n) average case.
In worst case pivot might divide the array in 1 an n-1 always, hence worst case time will be T(n) = T(n-1)+O(n) = O(n2).

Find minimum in a stack


Question: Design a data structure where it supports LIFO and a function min which gives min of the elements present at the moment in that structure.

Solution: To implement LIFO we can use Stack data structure, but to maintain current minimum we can use auxiliary space, here I am implementing it using another auxiliary stack. Initialize auxiliary stack with first element pushed in the stack as it would be the minimum at present. Now whenever a new element is pushed we check whether it is less than top element in auxiliary stack?if this condition satisfies then push it to auxiliary stack too. While popping through the stack, again check whether top of auxiliary is same as popped element, then pop from auxiliary also. At any time top of auxiliary will give min of the elements present in the stack.

Following program implements above logic.
/**
 * @author vikky.agrawal
 * Min should return minimum of elements present at the moment in stack.
 * 
 */

public class StackImpl {

 Node top =null; 
 
 public static void main(String[] arg){ 
   
  //Find min implementation
  
  StackImpl stack1=new StackImpl();
  StackImpl auxiliary=new StackImpl();
  
  for (int i = 1; i < 10; i++) {
   int data=(int) (Math.random() * 100);
   stack1.push(data);
   
   if(auxiliary.top==null){
    auxiliary.push(data);
   }else{
    int temp=auxiliary.peek();
    if(temp>0 && temp>data){
     auxiliary.push(data);
    }
   }
   
  }
  System.out.println("Original stack :");
  stack1.printStack();
  
  System.out.println("Auxiliary stack : ");
  auxiliary.printStack();
  
  //System.out.println("Min element right now is :"+auxiliary.peek());
  
  for (int i = 1; i < 5; i++) {
   
   int popped=stack1.pop();
   
   System.out.println("Popped element is :"+popped);
   
   if(auxiliary.peek()== popped){
    auxiliary.pop();
   }   
            System.out.println("Next Min element right now is :"+auxiliary.peek()); 
  }
 }
  
 /**
  * Helper functions for stack operations
  */
 
 public void push(int data){
  if(top==null){
   top=new Node(data);
  }else{
   Node temp=new Node(data);
   temp.setLink(top);
   top=temp;
  }
 }
 
 public int pop(){
  if(top==null){
   return -1;
  }else{
   Node temp=top;
   top=top.getLink();
   return temp.getData();
  }
 }
 
 public int peek(){
  if(top!=null){
   return top.getData();
  }else{
   return -1;
  }
 }
 
 
 public boolean isEmpty(){
  if(top==null)
   return true;
  return false;
 }
 
 
 public int size(){
  int size=0;
  Node temp=top;
  
  while(temp!=null){
   size++;
   temp=temp.getLink();
  }
  return size;
 }
 
 public void printStack(){
  Node temp=top;
  System.out.print("Top->\n");
  while(temp!=null){
   System.out.println(temp.getData()+"\n|");
   temp=temp.getLink();
  }
  System.out.println("/null");
 }
 
 /**
  * static inner class to be used for Stack Data Structure
  */
  static class Node{
   private int data;
   private Node link;    
      
      Node(){
            
      }
      
      Node(int data){
       //mergedList=new Node();
          this.setData(data);
          this.setLink(null);       
      }
      
      public int getData(){
          return this.data;
      }
        
      public Node getLink(){
          return this.link;
      }
      
      public void setData(int data){
          this.data=data;
      }       
      
      public void setLink(Node link){
          this.link=link;
      }  
 }
 
 
}