Binary Search

Search a sorted array by repeatedly halving the search interval.

Binary Search

Binary search finds a target value in a sorted sequence by repeatedly dividing the search space in half. At each step, it compares the target with the middle element and discards half of the remaining elements.

This reduces the problem size exponentially, which leads to logarithmic time complexity.

Problem

Given a sorted array $A$ of length $n$ and a value $x$, find an index $i$ such that

$$ A[i] = x $$

If no such index exists, return $-1$.

Key Idea

Maintain a search interval $[l, r]$. At each step:

  • Compute midpoint $m$
  • Compare $A[m]$ with $x$
  • Eliminate half of the interval

Algorithm

binary_search(A, x):
    l = 0
    r = length(A) - 1

    while l <= r:
        m = l + (r - l) // 2

        if A[m] == x:
            return m
        else if A[m] < x:
            l = m + 1
        else:
            r = m - 1

    return -1

Example

Let

$$ A = [1, 3, 5, 7, 9, 11] $$

and

$$ x = 7 $$

Steps:

step l r m A[m] action
1 0 5 2 5 move right
2 3 5 4 9 move left
3 3 3 3 7 found

Return index $3$.

Correctness

At each step, the algorithm maintains the invariant:

  • If $x$ exists in $A$, then it must lie within $[l, r]$

Each comparison removes half of the remaining candidates while preserving this invariant. When $l > r$, the interval is empty, so $x$ does not exist.

Complexity

case comparisons time
best $1$ $O(1)$
worst $\lfloor \log_2 n \rfloor + 1$ $O(\log n)$
average $O(\log n)$ $O(\log n)$

Space complexity:

  • Iterative: $O(1)$
  • Recursive: $O(\log n)$ due to call stack

Requirements

Binary search requires:

  • The array must be sorted
  • Random access to elements

If either condition fails, correctness or efficiency breaks.

Common Variants

Binary search generalizes to:

  • Lower bound (first $\ge x$)
  • Upper bound (first $> x$)
  • First true in monotone predicate
  • Search on answer space

These variants rely on the same invariant: monotonicity.

Implementation

def binary_search(a, x):
    l, r = 0, len(a) - 1
    while l <= r:
        m = l + (r - l) // 2
        if a[m] == x:
            return m
        elif a[m] < x:
            l = m + 1
        else:
            r = m - 1
    return -1
func BinarySearch(a []int, x int) int {
    l, r := 0, len(a)-1
    for l <= r {
        m := l + (r-l)/2
        if a[m] == x {
            return m
        } else if a[m] < x {
            l = m + 1
        } else {
            r = m - 1
        }
    }
    return -1
}