IID.systems
ProfileServicesFormal MethodsAI AlignmentEssaysBookSchoolGitHub日本語
日本語

Binary Search: Keep Discarding Half

Why one comparison with the middle lets us ignore half the candidates: the sorted-order requirement, O(log n), boundary search, and the classic 100-floor two-egg problem

What is binary search?

Binary search finds a target in sorted data. It examines the middle of the current range and uses whether the target is greater or smaller to reduce the next range by half.

The important part is not merely looking at the middle. Because the data is in ascending order, no value smaller than the middle can be on its right, and no larger value can be on its left. That fact justifies discarding one side without examining it.

1

Choose the middle

Treat low through high as the current candidate range and examine its middle element at mid.

2

Compare

Compare the middle value with the target and decide whether it matches or the target must be to the left or right.

3

Discard half

Use the sorted order to remove the side where the target cannot possibly exist.

The essence of binary search is not examining the middle; it is using one decision to discard half the candidates with a proof that the answer is not there.


Trace a search for 55

Use the same data as the visualization: 20 values from 5 through 100 in steps of 5. low and high mark the two ends of the range where the answer may still exist.

Searching for 55 in [5, 10, 15, ..., 95, 100] check search range middle decision 1 index 0..19 50 55 > 50 -> discard the left half 2 index 10..19 75 55 < 75 -> discard the right half 3 index 10..13 60 55 < 60 -> discard the right half 4 index 10..10 55 match! Found among 20 candidates with 4 comparisons

The first comparison shows that 55 is greater than 50, so ten values at or below 50 are removed at once. Next, values from 75 upward are removed, then values from 60 upward. The remaining value, 55, matches.

Every step preserves this condition: if the target exists in the array, it lies between low and high. This is a loop invariant. Showing that each range update preserves it is the basis for arguing that the algorithm is correct.


Why is it O(log n)?

Linear search may need n comparisons for n candidates. Binary search changes the candidate count from n to n/2, n/4, n/8, and so on with each comparison.

Linear search: O(n)

Among one million values, a target at the end can require one million comparisons. Doubling the data roughly doubles the work.

Binary search: O(log n)

Even one million sorted values require at most about 20 comparisons. Doubling the data generally adds only one comparison.

Keep narrowing until n / 2^k <= 1, so k >= log2(n)

Twenty values take at most five comparisons, about one million take at most 20, and about one billion take at most 30. The value of discarding half grows with the data set.

The O(log n) running time assumes a structure such as an array where the middle element can be accessed immediately. A linked list takes time to walk to the middle, so reducing the number of comparisons alone does not give the same total speed.


Implement it in TypeScript

In the basic implementation, both low and high belong to the search range. Compare the middle only while a range remains, expressed as low <= high.

function binarySearch(sorted: number[], target: number): number { let low = 0 let high = sorted.length - 1 while (low <= high) { // This form avoids overflow from low + high const mid = low + Math.floor((high - low) / 2) const value = sorted[mid] if (value === target) return mid if (value < target) low = mid + 1 else high = mid - 1 } return -1 }

Move right with low = mid + 1 and left with high = mid - 1. mid has already been compared, so it must leave the candidate range. Forgetting +1 or -1 can select the same middle forever and prevent termination.

This version returns any one matching element. When duplicate values exist, finding the first or last matching position requires a boundary-search variant that continues left or right after a match.


From finding a value to finding a boundary

Binary search is not limited to locating a value. If a decision is false up to some point and true from then onward, binary search can find the first true position. This property is called monotonicity.

floor: 1 2 3 ... 41 42 | 43 44 ... 100 breaks?: false false false ... false false | true true ... true ^ first true boundary

If predicate(mid) is true, the answer is mid or somewhere to its left. If it is false, the answer lies to the right. Either decision still discards half the candidates.

function firstTrue( low: number, high: number, predicate: (value: number) => boolean ): number { let answer = high + 1 // Returned when there is no true value while (low <= high) { const mid = low + Math.floor((high - low) / 2) if (predicate(mid)) { answer = mid high = mid - 1 // Look for an earlier true value } else { low = mid + 1 } } return answer }

The first product price over a budget, the fewest servers that meet capacity, or the shortest duration that satisfies a condition can all be understood as searches for a minimum successful value or maximum failing value.


A famous puzzle: 100 floors and two eggs

Now consider a classic interview puzzle. It initially looks exactly like binary search, but an additional constraint changes which algorithm is best.

The problem

You have a 100-floor building and two eggs of equal strength. Find the highest floor F from which an egg can be dropped without breaking. It survives at F and below and always breaks above F. An unbroken egg can be reused, but a broken one cannot. Which floors minimize the number of drops in the worst case?

About the label 'Google interview problem'

This puzzle is widely described as an old Google interview or hiring-test question, and some candidates report receiving it in a Google interview. Google has not published it as an official past paper, however, and it is also attributed to companies such as Microsoft. We therefore use 'a classic puzzle famous as a Google interview problem' as a popular label rather than a verified origin.

As the floor rises, the result changes exactly once from survives to breaks, so the predicate is monotonic. Does that mean we should start at floor 50 and keep halving?

With unlimited eggs: binary search

Try floor 50, then continue in floors 1-49 or 51-100 according to the result. If losing an egg does not prevent future tests, the 101 possible boundaries take at most about seven drops.

With two eggs: not plain binary search

If the first egg breaks at floor 50, only one remains. Letting it break again at floor 25 would make continuation impossible, so the lower floors must be checked one at a time. The decision that discards half also consumes a resource.

The optimal strategy first drops an egg at floor 14. If it survives, go 13 floors higher to 27, then 12 higher to 39, reducing the interval by one each time. When it breaks, use the second egg one floor at a time above the last safe floor.

Floors for dropping the first egg: 14 -> 27 -> 39 -> 50 -> 60 -> 69 -> 77 -> 84 -> 90 -> 95 -> 99 -> 100 +13 +12 +11 +10 +9 +8 +7 +6 +5 +4 (stop at 100) When it breaks: Use the second egg one floor at a time from just above the last safe floor Keep the worst case at 14: 1 + 13 = 2 + 12 = 3 + 11 = ... = 14

14 + 13 + 12 + ... + 1 = 105 >= 100

13 + 12 + 11 + ... + 1 = 91 < 100

Suppose the worst case allows d drops. If the first egg breaks on drop one, the second can check d-1 remaining floors; if it breaks on drop two, the second can check d-2. The most floors covered are therefore d + (d-1) + ... + 1. Thirteen drops cover only 91 floors, while 14 cover 105. A worst case of 14 for 100 floors is both achievable and minimal.

The lesson of this classic puzzle is less 'use binary search' than 'recognize when binary search is valid.' The boundary is monotonic, but destructive queries and a limit of two eggs make repeated halving non-optimal.


Summary

1

Binary search uses sorted order or monotonicity to discard half that provably cannot contain the answer. Unsorted data provides no such justification.

2

Halving the candidates on every step gives O(log n): even one million values require at most about 20 comparisons.

3

An implementation must preserve the meanings of low and high and its loop invariant, and remove the compared mid. Boundary search can find the first true or last false position.

4

The 100-floor two-egg puzzle shows how a resource constraint can make binary search non-optimal even with a monotonic boundary. Decreasing intervals of 14, 13, 12, and so on give the minimal worst case of 14 drops.