Binary Search
Introduction
Binary search is a classic algorithm used to quickly find the position of a target value within a sorted collection. It repeatedly divides the search interval in half, discarding the half that cannot contain the target. Because of this halving behavior, binary search runs in logarithmic time: O(log n).
If you are new to complexity analysis, review our guide to Big-O Notation. Also see our overview of Arrays, since binary search is most commonly applied to sorted arrays.
When to use binary search
Use binary search when:
- Your data is already sorted, or you can afford to sort it once and then perform many searches.
- You need fast lookups with minimal extra memory.
- You are searching in a space where you can define an ordering and midpoints (e.g., numbers, strings, or even an implicit search space like answer ranges in optimization problems).
Avoid binary search when:
- The data changes frequently (insertions/deletions) and maintaining sorted order is costly.
- You need average-case
O(1)lookups with frequent updates; a hash table might be a better fit.
How it works (high level)
- Start with two pointers:
leftat the beginning andrightat the end of the array. - Compute
mid = floor((left + right) / 2). - Compare
arr[mid]with thetarget:- If equal, return
mid. - If
arr[mid]is less thantarget, search the right half (left = mid + 1). - Otherwise, search the left half (
right = mid - 1).
- If equal, return
- Repeat until
leftpassesright. If not found, return a sentinel (e.g.,-1).
Iterative implementation
Below are iterative implementations in three languages. All return the index of target if found, or -1 if not found.
Recursive implementation
Binary search can also be implemented recursively. While concise, be mindful of recursion depth for extremely large inputs.
Complexity
- Time complexity:
O(log n)comparisons in the worst and average cases. - Space complexity:
- Iterative:
O(1)additional space. - Recursive:
O(log n)due to call stack depth.
- Iterative:
Common pitfalls and edge cases
- Unsorted input: Always ensure the array is sorted in the same order you’re searching.
- Overflow in midpoint calculation: In languages with fixed-width integers, compute
midasleft + (right - left) / 2to avoid overflow. - Duplicates: If the array contains duplicates and you need the first or last occurrence, adjust the algorithm to continue searching even after finding a match.
- Off-by-one errors: Carefully verify loop conditions (
left <= right) and updates toleft/right.
Variations
Binary search is more than a lookup algorithm. It’s a technique that appears in many problems:
- Searching for the first/last occurrence of a value.
- Finding
lower_bound/upper_bound(first element >=target, first element >target). - Searching answers in a monotonic predicate space (a.k.a. “binary search on answer”).
Practice prompts
Try implementing these variations:
- Return the index of the first occurrence of
targetin a sorted array with duplicates. - Given a sorted array, return the index where
targetshould be inserted to keep the array sorted. - Given
isPossible(x)that returns true ifxis possible and false otherwise, find the smallestxthat is possible within a range.