Lesson 6 of 8 · 48 min
Modified binary search
Boundary-safe binary search, rotated arrays, first/last occurrence, and search-on-answer (Koko, ship packages) with capacity-planning metaphors.
Binary search is not only “find in sorted array”
Key idea
feasible(x) → bool and feasible is true for all y≥x (or all y≤x), you can binary search the boundary. The coding problem reduces to inventing feasible, not inventing a clever closed form.Classic BS and first/last
1LOWER BOUND — first index with a[i] >= target (sorted a)23def lower_bound(a: list[int], target: int) -> int:4 lo, hi = 0, len(a) # hi exclusive5 while lo < hi:6 mid = (lo + hi) // 27 if a[mid] >= target:8 hi = mid9 else:10 lo = mid + 111 return lo # in [0, n]; n means all < target1213# First/last occurrence: lower_bound(t) and lower_bound(t+1)-1 with existence checks.Rotated sorted array
1SEARCH IN ROTATED SORTED ARRAY — identify sorted half23def search_rotated(a: list[int], target: int) -> int:4 lo, hi = 0, len(a) - 15 while lo <= hi:6 mid = (lo + hi) // 27 if a[mid] == target:8 return mid9 if a[lo] <= a[mid]: # left half sorted10 if a[lo] <= target < a[mid]:11 hi = mid - 112 else:13 lo = mid + 114 else: # right half sorted15 if a[mid] < target <= a[hi]:16 lo = mid + 117 else:18 hi = mid - 119 return -1Search-on-answer: Koko and ship packages
1SEARCH ON ANSWER — capacity to ship packages within D days23def ship_within_days(weights: list[int], days: int) -> int:4 def feasible(cap: int) -> bool:5 need, cur = 1, 06 for w in weights:7 if w > cap:8 return False9 if cur + w > cap:10 need += 111 cur = 012 cur += w13 return need <= days1415 lo, hi = max(weights), sum(weights)16 while lo < hi:17 mid = (lo + hi) // 218 if feasible(mid):19 hi = mid20 else:21 lo = mid + 122 return lo2324# O(n log S) with S = sum(weights). Narrate lo/hi meaning: min possible cap vs max.Key idea
Common mistake
“Binary search mid must always be an array index.”
Common mistake
“If feasible is expensive, binary search is wrong.”
Koko as the canonical search-on-answer drill
1KOKO EATING BANANAS — search-on-answer twin of ship packages23def min_eating_speed(piles: list[int], h: int) -> int:4 def hours(k: int) -> int:5 return sum((p + k - 1) // k for p in piles)67 lo, hi = 1, max(piles)8 while lo < hi:9 mid = (lo + hi) // 210 if hours(mid) <= h:11 hi = mid12 else:13 lo = mid + 114 return lo1516# Same skeleton as ship_within_days — only feasible changes.17# That sentence is the transfer skill interviewers grade.Key idea
Binary Search — NeetCodeNeetCodeInterview prep
- 01“When search-on-answer?” → minimize/maximize X with monotonic feasible(X).
- 02“Koko template?” → lo=1 hi=max pile; feasible hours ≤ h; minimize lo.
- 03“Ship packages lo/hi?” → lo=max(weight) hi=sum; feasible days ≤ D.
- 04“Rotated array key?” → at mid, at least one half is sorted; discard half via range test.
- 05“First occurrence?” → lower_bound style; do not scan linearly after find.
- 06“Infinite loop causes?” → mid computed wrong; lo/hi not moving; use hi=mid vs mid-1 carefully.
- 07“Duplicates in rotated?” → when equals blur sorted half, may shrink lo/hi linearly worst case.
- 08“Complexity speech?” → O(log n) index BS; O(n log RANGE) search-on-answer.
- 09"Overflow-safe mid?" -> lo + (hi-lo)//2.
- 10"Answer-space examples?" -> Koko, ship packages, split array largest sum, min max distance.
- 11"Rotated half choice?" -> find sorted half; if target in range search there else other.
- 12"Lower bound?" -> first i with a[i] >= target; hi exclusive template.
- 13"When is BS wrong?" -> when the predicate is not monotonic.
- 14"Complexity with expensive P?" -> O(P_cost * log domain); state P_cost explicitly.
articleSorting & searching — Tech Interview HandbookTech Interview HandbookdocsNeetCode — Koko Eating BananasNeetCodedocsLeetCode — Capacity To Ship Packages Within D DaysLeetCodearticleAlgoMaster patternsAlgoMasterWrite feasible(x) first as a pure function. If you cannot unit-test feasible on paper, the binary search shell will only hide the bug.
Templates: lower bound + answer-space (Koko)
1LOWER BOUND — first index with a[i] >= target23def lower_bound(a: list[int], target: int) -> int:4 lo, hi = 0, len(a) # hi exclusive5 while lo < hi:6 mid = lo + (hi - lo) // 27 if a[mid] < target:8 lo = mid + 19 else:10 hi = mid11 return lo # in [0..n]; n means all < target1213# Invariant: answer lives in [lo, hi). Prefer this over ad-hoc branches.14# upper_bound: first index with a[i] > target (change < to <=).1KOKO EATING BANANAS — binary search on answer23def min_eating_speed(piles: list[int], h: int) -> int:4 def hours(k: int) -> int:5 return sum((p + k - 1) // k for p in piles)67 lo, hi = 1, max(piles)8 while lo < hi:9 mid = lo + (hi - lo) // 210 if hours(mid) <= h:11 hi = mid12 else:13 lo = mid + 114 return lo1516# hours(k) decreases as k grows — monotonicity licenses BS on speed.17# Complexity: O(n log M) where M = max(piles).Common mistake
"Binary search only works on arrays of numbers."
Common mistake
"mid = (lo+hi)//2 is always fine."
Key idea
Koko Eating Bananas — NeetCodeNeetCodearticleSorting & Searching cheatsheet — TIHTech Interview HandbookarticleBinary search framework — LabuladongLabuladongCheckpoint
“Minimum capacity to ship all packages within D days, packages must stay in order.” First words out of your mouth?
Checkpoint
feasible(cap) is true for all cap ≥ C*. Your binary search should return?
Checkpoint
Rotated array search: a[lo] <= a[mid], target < a[lo]. Where next?
Checkpoint
Off-by-one: while lo < hi; if feasible(mid): hi=mid; else lo=mid. Bug?
Checkpoint
Production: “smallest number of workers so nightly ETL finishes by 6am.” Interview framing?
Can you invent feasible(x) for a novel capacity prompt and code lower-bound binary search without infinite loops?
Takeaways
- Binary search domains: indices OR answer values.
- Search-on-answer when feasible is monotonic.
- Rotated arrays: discard using the sorted half’s range.
- lo/hi movement rules prevent infinite loops.
- Production parallel: capacity planning / SLO search.
Next: trees and graphs — BFS/DFS choice, topo sort, clone, word ladder.
Sources
Free to read · better with Enzo
Learn it with Enzo
Save your progress, answer the checkpoints, and let Enzo quiz you on what you just read.