Algorithms

Binary Search

Find one item in a million in 20 lookups

Binary search is a divide-and-conquer search algorithm that finds a target value in a sorted array by repeatedly halving the search range. It runs in O(log n) time, meaning a one-million-element array takes at most 20 comparisons to search.

  • Time (worst, average)O(log n)
  • Time (best)O(1)
  • Space (iterative)O(1)
  • Requires sorted inputYes
  • StableN/A (search, not sort)

Watch the quick explainer

Watch the quick explanation, then try the guided practice below at your own pace.

Ready to try it? Go to guided practice →

Binary Search: guided practice

Find the next search index and explain which half can be ruled out.

Binary search works on sorted data. Compare the target with the middle element, then keep only the half that could still contain it. Stop when the target is found or the range is empty.

Practice is loading. You can use the original visualization and written explanation below.

Interactive visualization

Press play, or step through manually. The visualization is yours to drive — try it before reading on.

Open visualization fullscreen ↗

How binary search works

Imagine looking up a word in a printed dictionary. You don't start from page 1 — you flip to roughly the middle. If the word you want comes earlier alphabetically, you ignore the back half and repeat with the front half. Binary search does the same thing, on a sorted array, in code.

The algorithm tracks two indices, low and high, marking the boundaries of the range that could still contain the target. On each iteration:

  1. Compute the midpoint: mid = floor((low + high) / 2).
  2. Compare arr[mid] to the target.
  3. If equal, return mid — found.
  4. If arr[mid] is smaller, the target must be to the right; set low = mid + 1.
  5. If arr[mid] is larger, set high = mid - 1.
  6. Repeat until found, or until low > high (target absent).

The halving step is the magic. With a million-item array, the range halves to 500,000 → 250,000 → 125,000 → ... → 1 in just 20 comparisons. Linear search would average 500,000.

When to use binary search

  • Your data is sorted, or you can afford to sort it once and search many times.
  • You need an exact match, or the leftmost or rightmost match.
  • Random-access reads are cheap (an array, not a linked list).
  • You want predictable worst-case performance — binary search has no pathological inputs.

If your data changes constantly, the cost of keeping it sorted may outweigh the search savings. A hash table gives O(1) average lookups for unordered point queries. A balanced binary search tree gives O(log n) lookups and cheap ordered traversal.

Linear searchBinary search
Time complexity (worst)O(n)O(log n)
Requires sorted inputNoYes
1,000,000 items (worst case)1,000,000 comparisons20 comparisons
Best forTiny or unsorted arraysSorted arrays, repeated queries

Linear search can be preferable for small arrays or a few searches through unsorted data. The crossover depends on the implementation, hardware and workload; include any sorting cost when comparing them.

Pseudo-code

function binarySearch(arr, target):
    low = 0
    high = arr.length - 1
    while low <= high:
        mid = floor((low + high) / 2)
        if arr[mid] == target:
            return mid
        if arr[mid] < target:
            low = mid + 1
        else:
            high = mid - 1
    return -1   # not found

JavaScript implementation

function binarySearch(arr, target) {
  let low = 0;
  let high = arr.length - 1;
  while (low <= high) {
    const mid = low + Math.floor((high - low) / 2);
    if (arr[mid] === target) return mid;
    if (arr[mid] < target) low = mid + 1;
    else high = mid - 1;
  }
  return -1;
}

This form computes the midpoint without JavaScript bitwise coercion to 32 bits. The unsigned right shift operator truncates its numeric input to 32 bits, so it is not a general replacement for division on large indices.

Python implementation

def binary_search(arr, target):
    low, high = 0, len(arr) - 1
    while low <= high:
        mid = (low + high) // 2
        if arr[mid] == target:
            return mid
        if arr[mid] < target:
            low = mid + 1
        else:
            high = mid - 1
    return -1

Python's standard library also offers bisect.bisect_left and bisect.bisect_right — implementations of the leftmost/rightmost variants that you should use in production rather than rolling your own.

Common bugs and edge cases

  • Off-by-one in the loop condition. Use low <= high, not low < high — the latter misses the case where low and high converge on the target index.
  • Integer overflow on (low + high). In languages with fixed-width integers, prefer low + (high - low) / 2 with integer division when the bounds are nonnegative.
  • Forgetting to update boundaries. Always set low = mid + 1 or high = mid - 1, not mid, or the loop spins forever.
  • Searching unsorted data. The algorithm returns garbage silently — there's no runtime check.

Algorithm reference: NIST Dictionary of Algorithms and Data Structures: binary search. The interactive practice uses distinct integers so its search bounds and answers are unambiguous.

Frequently asked questions

Why is binary search O(log n)?

Each comparison eliminates half of the remaining search range. Halving an n-element range repeatedly takes log₂(n) steps. For n = 1,000,000, that's about 20.

Does binary search work on unsorted arrays?

No. The whole algorithm depends on knowing that items left of the midpoint are smaller and items right are larger. Without sorted order, halving the range tells you nothing useful.

Is binary search faster than a hash table?

An existing hash table offers O(1) average lookup; binary search offers O(log n) worst-case lookup in a sorted array. Building the table or sorting the array also costs time. The better choice depends on repeated queries, ordering needs, memory and update costs.

What if the array contains duplicates?

Plain binary search returns any one matching index, undefined which. To find the leftmost or rightmost occurrence, modify the algorithm to keep searching one side after a match instead of returning immediately.

Can binary search work on a linked list?

Yes, but linked lists lack constant-time access to a midpoint. A careful implementation needs O(n) link traversals and O(log n) comparisons; repeatedly looking up indices from the head can cost more. Arrays are the usual choice for efficient binary search.