Binary Search

Problem

We have sorted array of some elements, and we have to find index of given element using Binary search (better than O(n) time complexity).

Solution

Here we are going to use Binary Search.  We can have two cases :

  1. Element exists in given array
  2. Element does not exist in given array

Element exists in given array

Firstly, let’s have a look into the case that this element exists in array.  Later we will consider the case, when this element might not exist. The essence of the algorithm lies in dividing array in two parts and choosing in which part the element might be.

For example, we have an array of integers, sorted in ascending order:

Given Integers : {0, 3, 5, 7, 9, 19, 20, 32, 53, 64, 69, 72}

Number to be Searched :  20.

Steps for Searching

  1. In the above array, index of 20 lies in range from 0 to 11 (length of array).
  2. First iteration: (from index 0 to 11)
    1. Find the middle index of this range: (0 + 11) / 2 = 5.5 ≈ 5.
    2. The element with index 5 is 19.
    3. 20 > 19 (at index 5), so it lies in the right half of array.
    4. we can move left bound of index range to index 6 (not 5, because the 5th element is 19 and 19 ≠ 20).
  3. Next Iteration: (from index 6 to 11)
    1. Let’s find the middle value in the right part (range from index 6 to 11).
    2. It will be index 8 ( (6 + 11) / 2 = 8.5 ≈ 8) and element with this index is 53.
    3. Since 20 < 53, it lies in the left part of range (from index 6 to 7).
  4. Last Iteration: (from index 6 to 7)
    1. Find the middle index of this range: (6 + 7) / 2 = 6.5 ≈ 6.
    2. Middle is element with index 6.
    3. Element with index 6 is 20, which we were looking for.

 

Binary search example

Binary search example

Here is a code, which does the binary search in Java:

public int binSearch(int[] array, int element) {
    int left = 0, right = array.length - 1;
    while(left != right) {
        int middle = (left + right) / 2;
        if(element > array[middle])
            left = middle + 1;
        if(element < array[middle])
            right = middle - 1;
        if(element == array[middle])
            return middle;
    }
    return left;
}

To visualize binary search algorithm we can use binary trees. Root of the tree is middle value of array. Element left to root is a middle value of range from the beginning to middle, and right to root element is middle of range from middle to the end. As example in given array left to 19 lies 0, right to 19 lies 53. And left to 53 is 20, right to 53 is 69. And so on.

 

Binary Tree

Binary Tree

Element does not exist in given array

Now about changes, which we will have to make if the element is not guaranteed to exist. It is quite easy: if left bound of range equals to right bound of range and the element is not we are looking for, we should alert that such element does not exists in array. We can also modify this algorithm in case there might be more than one valid answer (there is repeating of some elements). We have to iterate while left bound is not equal to right. Let us find index of first occurrence: if middle element of range equals to sought-for element, move right bound to middle position.

Other Use Cases of Binary Search

This algorithm is valid not only for arrays. Some other use cases are listed here :

  1. To find a root of N with a certain degree of accuracy. You just need to set left bound as 0, right bound as N and to divide this range by two, leaving some digits after point, while left bound and right bound has different values.
  2. To find a place where to insert new element, or to check if given element exists in array. For example, structures like Set uses binary trees, and binary trees, as you saw, are closely connected to binary search algorithm.

Performance

Binary search is very efficient in cases where your range is very big (for example, from 0 to 1 000 000 000). Using this algorithm, searching range decreases twice after each iteration! In the worst case you will find element in O(log(n)) time complexity. For example, we have 1024 elements. We will divide them until just one element left. 512, 256, 128, 64, 32, 16, 8, 4, 2, 1. We needed just 10 iterations instead of 1024. Using binary trees, shown above, you can easily count how many iterations would take searching concrete element from the range. The biggest minus of this algorithm is that you need array to be sorted, so if input array is not sorted, time complexity turns from O(log(n)) to O(n * log(n)) for quick sort.

Summary

There are standard binary search methods in class Arrays, so you could use them for int, double, short, byte, char, Object and other types (see more on https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html). But if you have created array of your own objects, or you just have an array sorted in reverse order, you will have to write binary search yourself for the concrete task. In conclusion, if you understand the principle of this algorithm, you can use it in real life to economy much time on searching anything optimal.

Like this post? Don’t forget to share it!

4 Comments

  1. Ayan Kocher

    Here is a recursive approach
    BinarySearch(A[0..N-1], value, low, high) {
    if (high < low) return -1 // not found mid = low + ((high - low) / 2) if (A[mid] > value)
    return BinarySearch(A, value, low, mid-1)
    else if (A[mid] < value) return BinarySearch(A, value, mid+1, high) else return mid // found }

Leave a Reply

Your email address will not be published. Required fields are marked *