Recursive Binary Search

Binary search implemented using recursion over a shrinking interval.

Recursive Binary Search

Recursive binary search expresses the same divide and conquer strategy as binary search, but uses function calls instead of a loop. Each call reduces the search interval by half.

This form is closer to the mathematical definition of the algorithm, though it introduces call stack overhead.

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$.

Algorithm

Define a recursive function over a subarray $[l, r]$.

recursive_binary_search(A, x, l, r):
    if l > r:
        return -1

    m = l + (r - l) // 2

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

Wrapper:

search(A, x):
    return recursive_binary_search(A, x, 0, length(A) - 1)

Example

Let

$$ A = [1, 4, 6, 8, 11, 15] $$

and

$$ x = 8 $$

Call sequence:

call l r m A[m] result
1 0 5 2 6 recurse right
2 3 5 4 11 recurse left
3 3 3 3 8 found

Return index $3$.

Correctness

The recursion maintains the invariant:

  • If $x$ exists in $A$, then it lies within the current interval $[l, r]$

Each recursive call reduces the interval size while preserving this invariant. When $l > r$, the interval is empty, so no valid index exists.

Complexity

case time
best $O(1)$
worst $O(\log n)$
average $O(\log n)$

Space complexity:

type space
recursion stack $O(\log n)$

Each recursive call adds one frame to the call stack.

Notes

  • This version matches the divide and conquer structure directly.
  • It is easier to reason about formally but less efficient in low level environments due to function call overhead.
  • Tail recursion elimination may convert this to an iterative form in some compilers, but this is not guaranteed.

Implementation

def recursive_binary_search(a, x, l, r):
    if l > r:
        return -1
    m = l + (r - l) // 2
    if a[m] == x:
        return m
    elif a[m] < x:
        return recursive_binary_search(a, x, m + 1, r)
    else:
        return recursive_binary_search(a, x, l, m - 1)
func RecursiveBinarySearch(a []int, x int, l, r int) int {
    if l > r {
        return -1
    }
    m := l + (r-l)/2
    if a[m] == x {
        return m
    } else if a[m] < x {
        return RecursiveBinarySearch(a, x, m+1, r)
    } else {
        return RecursiveBinarySearch(a, x, l, m-1)
    }
}