Binary Search

Binary search keeps a range that must hold the answer and halves it with every look, so a million candidates take about 20 steps.

Binary search: find the target's index

StopBinary search
numstarget

nums

  1. lo10
  2. 31
  3. 42
  4. 63
  5. 84
  6. 95
  7. 116
  8. 147
  9. 178
  10. hi209
  • CH1 lo
  • CH2 hi
The target could be anywhere from lo = 0 to hi = 9.
Typical cost O(log n) time, O(1) spaceFull lesson: Binary Search →

When to reach for it

  • The input is sorted, or the answers are: too small, then big enough.
  • One cheap check tells you which side of a candidate the answer is on.
  • A scan would work, but n is large.
  • You want the smallest or largest value that still works.

What stays true

The list is sorted, so everything left of a too-small middle is smaller still, and everything right of a too-big one is larger. Each move drops only numbers that can't be the target.

The target never leaves the range

StopBinary search
InvariantIf the target is in nums, it's between lo and hi.✓ Holds

nums

  1. lo20
  2. 51
  3. 82
  4. 123
  5. 164
  6. 235
  7. 386
  8. 567
  9. 728
  10. hi919
target23
  • CH1 lo
  • CH2 hi
The target could be anywhere from lo = 0 to hi = 9.

Break it

Each input here has tripped up a version of this code. The stage runs the one that gets it right.

The target is the last candidate standing. A loop that runs while lo < hi stops before checking it.

Binary search on the inputs that trip it up

StopBinary search

nums

  1. lo20
  2. 41
  3. 62
  4. 83
  5. 104
  6. hi125
target12
  • CH1 lo
  • CH2 hi
The target could be anywhere from lo = 0 to hi = 5.
Answer5Steps7

Variants

Search in rotated sorted array

StopBinary search

nums

  1. 40
  2. 51
  3. 62
  4. 73
  5. lohimid0✓4
  6. 15
  7. 26
target0nums[mid]0
  • CH1 lo
  • CH2 hi
  • CH3 mid
9/9

One half around any middle is sorted, and its ends say whether the target can be there.

Step through it →

Find minimum in rotated sorted array

StopBinary search

nums

  1. 40
  2. 51
  3. 62
  4. 73
  5. lohi0✓4
  6. 15
  7. 26
  • CH1 lo
  • CH2 hi
8/8

Compare the middle with the right end to find which side the drop is on.

Step through it →

Koko eating bananas

StopBinary search

speed

piles36711
h8
  • CH1 left
  • CH2 right
14/14

Search the speeds, not the piles: too slow, then fast enough from the answer on.

Step through it →

Longest increasing subsequence

StopBinary search

nums

  1. 10
  2. 9
  3. 2
  4. 5
  5. 3
  6. 7
  7. 101
  8. 18

tails

  1. 20
  2. 31
  3. 72
  4. 183
len(tails)4
38/38

Each number binary-searches a sorted list of the smallest tail for each length.

Step through it →

The code

The same algorithm in plain Python. The lit line is the one the current frame came from.

Binary search: find the target's index

StopBinary search

nums

  1. lo10
  2. 31
  3. 42
  4. 63
  5. 84
  6. 95
  7. 116
  8. 147
  9. 178
  10. hi209
target11
  • CH1 lo
  • CH2 hi
The target could be anywhere from lo = 0 to hi = 9.
search.py
def search(nums, target):    lo, hi = 0, len(nums) - 1    while lo <= hi:        mid = lo + (hi - lo) // 2        if nums[mid] == target:            return mid        if nums[mid] < target:            lo = mid + 1        else:            hi = mid - 1    return -1

Drill it