Binary Search - Iterative approach and variation for different problems

Binary Search algorithm is one of the efficient search algorithm with o(log N) time complexity.

This algorithm works best in sorted array.

Logic:

  1. If we know the size of the array, compute the MID point (using length of array, LOW will be 0, HIGH will be array length)

  2. If the element at the mid point is GREATER than the search element then search LEFT side of array.

    i.   This is achieved by setting the HIGH = MID-1;

  3. Else if the element at the mid point is LESSER than the search element then search RIGHT side of array

    i.  This is achieved by setting the LOW = MID +1;

  4. Else if the element at the mid point is EQUAL then return the mid point or index.

  5. Repeat the above step until the LOW >= HIGH;

Iterative approach code

public int binarySerach(int[] input, int item) {
     int low = 0;
     int high = input.length-1;
     while (low <= high ) {

        // mid point is cacluated low + (high - low)/2 to avoid overflow
        // instead of (low+high)/2; assume if the INT max is 100, 
        // if search element is on the right side say 89th element. 
       // (50+100) will max out Integer max in this case.
       // mathematically (2*low + high - low )/2 = (high + low )/2

       int mid = low +(high - low)/2; 

       if(item > input[mid]) {
                low = mid+1;
        }else if (item < input[mid]){
                high = mid-1;
        }else{ // condition where the mid element is equal
              return mid;
        }
     }
    return -1;   //if there are no match return -1 as index, array can't have -1 index
 }

1. Identifying first occurrence of duplicate item in sorted array

  Given a sorted array with duplicate elements identify the first occurrence of an element.

Sample input and output:

{1,2,3,4,5,5,5,5,6,7}  //first occurrence of 5, expected output is 4 (index value)

In this case if the search item is identify, we just need to look towards the left for the same element. If the same element exists, the current index pointing to the element will be first occurrence.

 public int findFirstOccurrence(int[] input, int item) {
       int low = 0;
       int high = input.length-1;
       int occurrence = -1;

        while (low <= high ) {
             int mid = low + (high-low)/2;

             if(item > input[mid]) {
                     low = mid+1; //search right half [mid+1, high]
              }else if(item < input[mid]){
                      high = mid-1; //search left half + middle [low, mid]
              }else { // when item found, check towards LEFT for first occurrence
                       occurrence = mid;
                       high = mid-1; // To search left, set HIGH = mid-1 which will search left
              }
        }
       return occurrence;
 }

2. Identifying last occurrence of duplicate item in sorted array

 public int findLastOccurrence(int[] input, int item) {

          int low = 0;
          int high = input.length-1;
          int occurrence = -1;

          while (low <= high ) {
                int mid = low + (high-low)/2;
                if(item > input[mid]) {
                     low = mid+1; //search right half [mid+1, high]
                 } else if(item < input[mid]){
                     high = mid-1; //search left half + middle [low, mid]
                 }else { // when item found, check towards RIGHT for last occurrence
                     occurrence = mid;
                    low = mid+1; // To search right, set LOW = mid+1 which will search same element
                 }
           }
          return occurrence;
 }

3: Identifying the pivot element of sorted rotated array

  Given an array which is rotated, identify the pivot, where there are no duplicate elements (Pivot in this case is the largest number which divides two sorted subarray)

Sample input and expected output:

{9,1,2,3,4,5}; // Pivot is on the left side of mid element, output is 0, item= 9 {4,5,6,1,2,3}; // Pivot is on the mid index itself, output is mid 2, item= 6 {5,6,7,9,10,12,13,3,4}; // Pivot is on the right side of mid item, output is 6, item= 13

  This can be seen like two ascending sorted array.    Below code will return the index

    public static int findPivot(int input[]) {
        int low=0; int high= input.length-1;
        int mid =-1;
        // Safe condition, if there are not rotation.
        //case 1
        if( input[low] < input[high]) 
            return high;

        while(low <=high) {
            mid = low+(high-low)/2;

            //case 2
            //if the element at the mid position is greater than the next element
            // then return the mid {3,4,5,1,2} // mid pos=2 A[mid] =5; 5>1, mid is pivot (5)
            if(mid < high && input[mid] > input[mid+1] ) {
                return mid;
            }
            // case 3
            //if the element at the mid position is less than the previous element
            // then return the mid-1 {4,5,1,2,3} //mid pos=2 A[mid] =1; 1<5, mid-1 is pivot (5) 
            if( mid > low && input[mid] < input[mid-1]) {
                return mid-1;
            }
            // case 4
            //if the element at start is greater than element at mid, then pivot/max should be on the left
            //1st iteration - low=0 high=4 
            // {5,1,2,3,4}; mid=(0+(4-0)/2)=2, A[2]=2, A[0]=5;  5> 2 true
            // set high = mid-1= 2-1 =1, 
            //2nd iteration from low=0 to high=1
            // {5,1,2,3,4}; mid=0-(1-0)/2=0, A[0]=5, A[mid+1]=1;  5> 1 true (Case 2) returns mid
            // set high = mid-1= (1-1) =0; 
            if(input[low] > input[mid]) {
                high = mid-1;
            }else   // Case 5 
                if(input[mid] > input[high]) {
                low  = mid+1;
            }
        }
        return -1;
    }

4. From sorted array from 0 to N find the smallest missing item

  • Given the array of sorted items expected to start from 0,1,2,....N find the smallest missing number.

    Logic:

    • Since the index of the array should match item here, we can use the binary search.
    • If the item is matching the index of the array, we need to search towards right side
    • If the item is less than the mid element then the missing value in the left side
    • Additional case, if the first item is not 0, then the 0 is the smallest
    • If the last item in the array is equal to the last index, return the length item or simply return -1 (sequence correct)

Sample input and expected output

// {0,1,2,4,5,6,7,8} missing is 3 output will be three

    public static int binarySearchMissing(int input[]) {

        int low = 0;
        int high = input.length -1;
        int mid = 0;

        if(input[0] !=0 ) {
            return 0;
        }
        if(input[high] == high) {
            return high;
        }
        while (low<=high) {
            mid = low + (high-low)/2; 
            //Try the left side
            if(input[mid]>mid) {
                high=mid-1;
            }else 
            //try right side 
            if(input[mid]<mid) {
                low=mid+1;
            }else {
                low =mid+1;
            }

        }
        return mid+1; //since the index value +1 gives missing smallest item
    }