Skip to content

Searching: Linear & Binary

Checking every element, against halving the problem each step. One million elements: a million comparisons, or twenty.

Class 11 to 12intermediate35 min4 lessons1 interactive lab
By the end you will be able to
  • Trace binary search with lo, mid and hi pointers
  • Explain why binary search requires sorted input
  • Decide when sorting first is worth it and when it is not
  • Write the loop without the two classic bugs

Cost at a glance

linear
O(n)
binary
O(log n)
binarySpace
O(1) iterative
sortThenSearch
O(n log n + k log n)

Lesson 1 of 4

Linear search, and why it survives

Linear search checks index 0, then 1, and keeps going until it finds the target or runs out of array. It is O(n), it makes no assumptions, and it is the only option on unsorted data. On average it examines half the array when the value is present, and all of it when the value is absent.

It is not a bad algorithm, it is the correct algorithm for a small or unsorted collection. For twenty items the difference against anything cleverer is unmeasurable, and it works on data you cannot sort, such as a stream you are reading once.

Interactive lab

Linear and binary search

Run both on the same target and compare the comparison counts, with lo, mid and hi marked and the discarded half dimmed rather than hidden.

Linear and binary search

O(log n) · requires sorted input
4
0
8
1
15
2
16
3
23
4
42
5
55
6
68
7
0comparisons0 of 8 ruled out without being read
1 / 8

Start

Binary search for 68. The array is sorted, which is the whole premise: comparing against any element tells you which side the target must be on.

Continue

Lesson 2 of 4

Binary search: halve, don't walk

Binary search keeps a window of indexes that could still contain the target, described by lo and hi. It compares the middle element with the target: equal means done, too small means the target must be to the right so lo moves past mid, too large means the target must be to the left so hi moves before mid. Every comparison discards half the remaining window.

Step it in the lab and watch the counter next to the dimmed cells: those elements were ruled out without ever being read. That is the whole trick, and it is only sound because the array is sorted. On unsorted data the comparison tells you nothing about which side to keep, which is why the lab refuses to run rather than returning a wrong answer.

The number of halvings needed to reduce n to 1 is log₂ n. A thousand elements take at most 10 comparisons, a million take 20, a billion take 30. Adding a thousand times more data costs ten more comparisons.

Continue

Lesson 3 of 4

Is sorting first worth it?

Sorting costs O(n log n), so for a single lookup it is not worth it: one linear scan at O(n) is cheaper than sorting to enable a O(log n) search. The calculation changes when you search repeatedly. Sort once at O(n log n), then answer k queries at O(log n) each, and the total is O(n log n + k log n) against O(k·n) for repeated scanning. By the time k is in the thousands the sorted version wins overwhelmingly.

This is the reasoning behind database indexes. An index is a sorted structure maintained alongside the table precisely so that lookups stop being full scans, and the cost is paid on every write instead. If your workload is one write and one read, an index is a waste; at a thousand reads per write it is the difference between a working product and a broken one.

Continue

Lesson 4 of 4

The two classic bugs

Binary search is famously easy to get subtly wrong. The first bug is the loop condition: `while (lo < hi)` skips the case where the window has narrowed to one element, so a target sitting there is reported missing. With inclusive bounds the condition must be `lo <= hi`.

The second is the update. Writing `hi = mid` instead of `hi = mid - 1` leaves the already-rejected middle element inside the window, and when lo and hi meet on it the loop stops making progress and spins forever. Because mid has just been compared and rejected, both updates must step past it: `lo = mid + 1` or `hi = mid - 1`.

There is a third, historical bug worth knowing: computing the midpoint as `(lo + hi) / 2` can overflow a fixed-size integer on very large arrays, which is why languages with fixed-width integers use `lo + (hi - lo) / 2`. JavaScript numbers make this harmless in practice, but the same code in Java or C is a real defect.

Continue

Worked examples

Read the code, then change it

Copy any example into the playground and break it on purpose. That is the fastest way to learn what each line is holding up.

Binary search, written correctlyJavaScript
function binarySearch(sorted, target) {
  let lo = 0;
  let hi = sorted.length - 1;
  let comparisons = 0;

  while (lo <= hi) {            // <=, or a one-element window is skipped
    const mid = lo + Math.floor((hi - lo) / 2); // overflow-safe form
    comparisons += 1;
    if (sorted[mid] === target) return { index: mid, comparisons };
    if (sorted[mid] < target) lo = mid + 1;     // step PAST mid
    else hi = mid - 1;                          // step PAST mid
  }
  return { index: -1, comparisons };
}

const data = Array.from({ length: 1000 }, (_, i) => i * 3);
console.log(binarySearch(data, 2997)); // near the end, still ~10 comparisons
console.log(binarySearch(data, 4));    // absent

// Linear search on the same lookup, for contrast:
let linear = 0;
for (const value of data) { linear += 1; if (value === 2997) break; }
console.log('linear comparisons:', linear);

Practice

Work these out yourself

No answer key here on purpose: these are the questions worth thinking through before you move on. Open one and work it out.

0/4 attempted

Assessment

Check your understanding

Answer each question, then read the explanation. That is where the learning is.

0/5
  1. Question 1: At most how many comparisons does binary search need on 1,000,000 sorted elements?
    Question 1 / 5

    At most how many comparisons does binary search need on 1,000,000 sorted elements?

    Select an option first
  2. Question 2: What does binary search require that linear search does not?
    Question 2 / 5

    What does binary search require that linear search does not?

    Select an option first
  3. Question 3: You need one single lookup in an unsorted array of 50,000 items. What is fastest?
    Question 3 / 5

    You need one single lookup in an unsorted array of 50,000 items. What is fastest?

    Select an option first
  4. Question 4: In a binary search with inclusive bounds, writing `while (lo < hi)` causes what?
    Question 4 / 5

    In a binary search with inclusive bounds, writing `while (lo < hi)` causes what?

    Select an option first
  5. Question 5: A sorted array grows from one million to one billion elements. Binary search now needs roughly how many more comparisons?
    Question 5 / 5

    A sorted array grows from one million to one billion elements. Binary search now needs roughly how many more comparisons?

    Select an option first
5 of 5 questions left.

Finished this topic?

0 of 4 lessons marked done. Marking the topic complete ticks the rest.