> Uploading knowledge... _
[░░░░░░░░░░░░░░░░░░░░░░░░] 0%
blog logo
> CHICIO CODING_Pixels. Code. Unplugged.

Binary Search

Binary Search is one of the most fundamental algorithms in computer science, widely used for efficiently searching in sorted structures. Its core idea is simple yet powerful: instead of scanning every element linearly, it repeatedly divides the search space in half, reducing the problem size exponentially at each step. This leads to a time complexity of O(logn)O(\log n), which is significantly faster than a linear scan for large datasets.

The algorithm

The algorithm works on the principle of divide and conquer. Given a sorted array, we compare the target element with the middle element. If the target equals the middle element, the search terminates successfully. If the target is smaller, the search continues in the left half; if larger, in the right half. This halving continues until the search space becomes empty or the element is found.

Here is a canonical TypeScript implementation:

function binarySearch(arr: number[], target: number): number {
  let left = 0;
  let right = arr.length - 1;

  while (left <= right) {
    const mid = Math.floor(left + (right - left) / 2);

    if (arr[mid] === target) {
      return mid;
    } else if (arr[mid] < target) {
      left = mid + 1;
    } else {
      right = mid - 1;
    }
  }

  return -1;
}

Several subtle but important details are worth noting:

  • the calculation of mid as left + (right - left) / 2 prevents integer overflow, which can occur if left + right exceeds the maximum integer value. While JavaScript/TypeScript numbers are safe, this is critical in languages like Java or C++.
  • Binary Search requires a sorted structure; using it on an unsorted array will lead to incorrect results.
  • The algorithm naturally lends itself to recursion, though iterative implementations are usually preferred for efficiency and avoiding stack overflow.

Binary Search is more than just a search algorithm. It forms the foundation for numerous patterns and problem-solving techniques, including:

  • Finding insertion positions in arrays
  • Detecting boundaries like first or last occurrences
  • Searching in rotated or partially sorted arrays
  • Solving “search the answer” problems where the solution space is numerical or monotonic

All these variations can be tackled with a few core adaptations of the basic Binary Search. For example, to search on rotated sorted arrays, we can modify the comparison logic to determine which half is properly sorted and adjust our search accordingly.

function search(nums: number[], target: number): number {
    let left = 0
    let right = nums.length - 1

    while (left <= right) {
        let mid = left + Math.floor((right - left) / 2)

        if (nums[mid] === target) {
            return mid
        }

        if (nums[left] <= nums[mid]) {
            if (nums[left] <= target && target < nums[mid]) {
                right = mid - 1
            } else {
                left = mid + 1
            }
        } else {
            if (nums[mid] < target && target <= nums[right]) {
                left  = mid + 1
            } else {
                right = mid - 1
            }
        }
    }

    return -1
};

Time and Space Complexity

Binary Search works by repeatedly halving the search space until the target element is found or the space becomes empty. At each step, only a single comparison is performed, resulting in very efficient logarithmic behavior.

The number of iterations depends on the size of the input array:

  • In all cases, the search space is halved at each step, so the number of iterations is O(logn)O(\log n).

For this reason:

  • Average time complexity: O(logn)O(\log n)
  • Worst-case time complexity: O(logn)O(\log n)

For what concerns space complexity, Binary Search can be implemented iteratively with no extra memory allocation:

  • Auxiliary space: O(1)O(1)
  • Recursion stack (if implemented recursively): O(logn)O(\log n)

As a result:

  • Average space complexity: O(1)O(1) iterative, O(logn)O(\log n) recursive
  • Worst-case space complexity: O(1)O(1) iterative, O(logn)O(\log n) recursive

Exercises

ExerciseDifficultyDescription
Find First and Last Position of Element in Sorted ArrayMedium

Given an array of integers nums sorted in non-decreasing order, find the starting and ending position of a given target value.

Find in Mountain ArrayHard

(This problem is an interactive problem.)

Find Minimum in Rotated Sorted ArrayMedium

Suppose an array of length n sorted in ascending order is rotated between 1 and n times. For example, the array nums = [0,1,2,4,5,6,7] might become:

Find Peak ElementMedium

A peak element is an element that is strictly greater than its neighbors.

Koko Eating BananasMedium

Koko loves to eat bananas. There are n piles of bananas, the ith pile has piles[i] bananas. The guards have gone and will come back in h hours.

Median of Two Sorted ArraysHard

Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays.

Random Pick with WeightMedium

You are given a 0-indexed array of positive integers w where w[i] describes the weight of the ith index.

Search a 2D MatrixMedium

You are given an m x n integer matrix matrix with the following two properties:

Search in Rotated Sorted ArrayMedium

There is an integer array nums sorted in ascending order (with distinct values).

Search Insert PositionEasy

Given a sorted array of distinct integers and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.