Wiki
Core11 min read

Searching: linear and binary

Scanning every element is O(n); binary search turns sortedness into O(log n) by halving the range each step.

Finding something is the most common thing a program does. If the data is unsorted, the only honest answer is to look at every element until you find it — O(n)O(n). But if the data is sorted, each look can discard half of what remains, and a billion elements take only about thirty comparisons.

Sortedness is a permission slip

Binary search does not make the elements easier to see; it uses the ordering to rule out whole ranges at once. That is why the array must be sorted first — the algorithm silently returns wrong answers on unsorted input, without any error.

Pick a target below and step through the shrinking window.

Pick a target and halve the window with each comparison

1
3
5
7
9
11
13
15
17
19
21
23
25
27
29
31
low = 0mid = 7high = 15

binary search

4 comparisons

linear search

11 comparisons

Each step discards half the remaining array, so the number of comparisons is at most log2(n) + 1 — around 4 here instead of up to 16. That speed-up is only available because the array is sorted; on unsorted data you must fall back to scanning.

Walk the array from the front, comparing as you go, and stop on a match:

def linear_search(a, target):
    for i, value in enumerate(a):
        if value == target:
            return i
    return -1

The cost is O(n)O(n): in the worst case the target is last or absent. It needs no precondition, works on linked lists and streams, and is the only option when the data is unordered.

Maintain a range [lo, hi] and test its midpoint:

def binary_search(a, target):
    lo, hi = 0, len(a) - 1
    while lo <= hi:
        mid = (lo + hi) // 2
        if a[mid] == target:
            return mid
        if a[mid] < target:
            lo = mid + 1
        else:
            hi = mid - 1
    return -1

Each iteration halves the range, so the loop runs at most ⌊log⁡2n⌋+1\lfloor \log_2 n \rfloor + 1 times. For n=109n = 10^9 that is about thirty comparisons instead of a billion.

Binary search needs a sorted array and an exact loop condition

Two classic bugs: using lo <= hi when the update can skip the answer, and computing mid in a way that can overflow (not an issue in Python, but a real one in C). Write mid = lo + (hi - lo) // 2 and prove the invariant that the target, if present, always lies inside [lo, hi].

Choosing, and the alternative

  • Unsorted data, searched once: linear scan.
  • Sorted data, searched many times: binary search.
  • Repeated lookups keyed by value: build a hash table once and search in O(1)O(1) average. Sorting plus binary search costs O(nlog⁡n)O(n \log n) to set up and O(log⁡n)O(\log n) per query; a dict costs O(n)O(n) to build and O(1)O(1) per query when keys are hashable.

Python exposes binary search directly through bisect, including bisect_left/bisect_right for insertion points.

Illustrative vs real

The demo uses sixteen small sorted integers so the low/mid/high window is visible; real arrays hold millions of items and the window narrows too fast to watch. The comparison count — about log⁡2n+1\log_2 n + 1 — is the same, and it is why binary search is the backbone of database indexes and ordered maps.

Check yourself

Eduspheria wiki · Programming & Data Structures, Algorithms

0 / 5 answered

  1. 1What is the worst-case time complexity of binary search on n sorted elements?
    Multiple choice
  2. 2About how many comparisons does binary search need for an array of 1024 elements?
    Numeric answer
  3. 3Binary search produces a correct result on an unsorted array.
    True / false
  4. 4Which Python standard-library module provides binary search on a sorted list?
    Short answer
  5. 5For repeated membership tests on unsorted data, which approach is usually best?
    Multiple choice

From the assignment paper

Modeled on NITJ AI-507, Assignment/Quiz

0 / 5 answered

  1. 1Which of the following algorithms uses the divide and conquer strategy?
    Multiple choice
  2. 2What is the best-case time complexity of selection sort?
    Multiple choice
  3. 3What is the best-case performance of bubble sort?
    Multiple choice
  4. 4How does insertion sort build its result?
    Multiple choice
  5. 5A linear search over 64 elements reaches the end without finding its target. How many comparisons did it make?
    comparisons
    Numeric answer

Where next: graph traversal — searching an entire network of nodes, not just a list.