Binary Search Visualization — Step by Step

Divides a sorted array in half each step, comparing the middle element with the target.

SearchingbeginnerUpdated

// quick answer

Binary Search is a searching algorithm that runs in O(log n) time on average with O(1) space. Divides a sorted array in half each step, comparing the middle element with the target.

How Binary Search Works

Binary Search works on sorted arrays by comparing the target with the middle element. If the target is smaller, it searches the left half; if larger, the right half. Each step eliminates half the remaining elements, giving O(log n) time. Requires the input to be sorted.

Binary Search Step by Step

Start with two pointers around the whole array

Binary Search keeps a live search range defined by two indices: low at the left edge and high at the right edge. Everything between them might contain the target; everything outside has been proven not to. Take the sorted array [3, 7, 12, 18, 25, 31, 42, 50] and search for 42. Initially low = 0 and high = 7 — all eight elements are candidates. The single precondition is that the array is sorted: the whole algorithm is built on the fact that comparing one element tells you which *side* of it the target must be on.

Check the midpoint and throw away half

Compute the midpoint: mid = ⌊(low + high) / 2⌋ = ⌊(0 + 7) / 2⌋ = 3, where the value is 18. Compare it with the target: 18 < 42. Because the array is sorted, the target cannot be at index 3 or anywhere to its left — indices 0 through 3 are eliminated in one comparison. Set low = mid + 1 = 4. Four elements gone, four remain: [25, 31, 42, 50]. This is the whole trick — each comparison discards half of whatever is left, no matter how large the array is.

Repeat until the range collapses on the target

Second iteration: the range is [4..7], so mid = ⌊(4 + 7) / 2⌋ = 5, value 31. Since 31 < 42, eliminate the left portion again: low = 6. Third iteration: range [6..7], mid = 6, value 42 — a match! The search finishes at index 6 after just 3 comparisons. A linear search scanning the same array would have needed 7. Watch this in the visualizer: the highlighted range shrinks by half each step, and eliminated elements gray out.

Why it is O(log n)

Each comparison halves the candidates: 8 → 4 → 2 → 1, so 8 elements need at most ⌈log₂ 8⌉ + 1 ≈ 4 checks. The payoff grows absurdly with size: 1,000 elements need about 10 comparisons, 1,000,000 need about 20, and a billion need about 30. Doubling the array adds exactly one comparison. That is what O(log n) means in practice — the work grows with the number of times you can halve n, not with n itself. It is the same halving idea that powers binary search trees.

When the target is missing

Search the same array for 20. Range [0..7], mid value 18 < 20 → low = 4. Range [4..7], mid value 31 > 20 → high = 4. Range [4..4], mid value 25 > 20 → high = 3. Now low = 4 and high = 3 — the pointers have crossed, meaning the range is empty and no element can equal 20. The loop condition low <= high fails and the search reports not-found. Usefully, low now points at index 4, exactly where 20 *would* be inserted to keep the array sorted — many libraries expose this as the insertion point.

Time & Space Complexity

Best CaseAverage CaseWorst CaseSpace
O(1)O(log n)O(log n)O(1)

Binary Search Pseudocode

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

Press play in the visualizer above to watch each line execute with live highlighting.

Binary SearchCode in JavaScript, Python & Java

JavaScript

function binarySearch(arr, target) {
  let low = 0;
  let high = arr.length - 1;

  while (low <= high) {
    const mid = Math.floor((low + high) / 2);

    if (arr[mid] === target) {
      return mid; // found
    }
    if (arr[mid] < target) {
      low = mid + 1; // target is in the right half
    } else {
      high = mid - 1; // target is in the left half
    }
  }
  return -1; // pointers crossed: not present
}

Python

def binary_search(arr, target):
    """Return the index of target in sorted arr, or -1 if absent."""
    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   # target is in the right half
        else:
            high = mid - 1  # target is in the left half

    return -1  # not found (low is the insertion point)

Java

public class BinarySearch {
    public static int binarySearch(int[] arr, int target) {
        int low = 0;
        int high = arr.length - 1;

        while (low <= high) {
            // low + (high - low) / 2 avoids int overflow
            int mid = low + (high - low) / 2;

            if (arr[mid] == target) {
                return mid;
            }
            if (arr[mid] < target) {
                low = mid + 1;
            } else {
                high = mid - 1;
            }
        }
        return -1; // not found
    }
}

When to Use Binary Search

  • Use it on sorted arrays with random access — the data must be ordered, and jumping to an arbitrary middle index must be O(1).
  • Use it when you search the same dataset many times: sorting once at O(n log n) and then answering every lookup in O(log n) quickly pays for itself.
  • Use the insertion-point variant (bisect in Python, lower_bound in C++) to find where a value belongs, not just whether it exists — the backbone of range queries on sorted data.
  • Do not use it on unsorted data — sorting first just to run one search costs O(n log n), more than a single linear search at O(n).
  • Do not use it on a linked list: reaching the midpoint takes O(n) walking, which destroys the logarithmic advantage.
  • If the data changes constantly (frequent inserts and deletes), keeping an array sorted is expensive — a hash table for exact lookups or an AVL tree for ordered lookups is usually the better structure.

Binary Search — Frequently Asked Questions

Why does binary search need sorted data?

The algorithm decides which half to discard based on a single comparison: if the middle element is smaller than the target, the target must lie to the right — but that inference is only valid when elements are in order. On unsorted data the target could be anywhere, so throwing away half the array risks throwing away the answer. Sortedness is what turns one comparison into information about many elements at once.

Is binary search always faster than linear search?

No. For tiny arrays (roughly a dozen elements) the simpler loop of linear search is often just as fast in practice. If the data is unsorted, sorting it first costs O(n log n), which is more than one O(n) linear scan. And on structures without constant-time indexing, like linked lists, binary search loses its advantage entirely. Binary search wins when data is already sorted and searched repeatedly.

Why is binary search O(log n)?

Every comparison halves the remaining search range: n candidates become n/2, then n/4, and so on until one remains. The number of halvings needed to get from n down to 1 is log base 2 of n. So a million-element array is resolved in about 20 comparisons, and doubling the array size adds only a single extra comparison.

What does binary search return when the target is not in the array?

The loop ends when the low and high pointers cross, proving the range is empty, and most implementations return -1 or a not-found signal. A useful detail: at that moment the low pointer sits exactly where the target would need to be inserted to keep the array sorted. Library versions like Python bisect and Java Arrays.binarySearch expose this insertion point.

Why do some implementations compute mid as low + (high - low) / 2?

In fixed-width integer languages like Java or C, the classic (low + high) / 2 can overflow when both indices are large: their sum may exceed the maximum int value and wrap around to a negative number. Writing low + (high - low) / 2 computes the same midpoint without the large intermediate sum. In JavaScript and Python, where numbers do not overflow this way, either form is safe.

Compare Binary Search

Related Algorithms

References & Further Reading