Binary search on the answer, without the off-by-one
TLEvision / 6 Aug 2026
Most binary search bugs aren't in the comparison. They're in the loop boundary, and they come from writing the loop before deciding what the invariant is.
Decide what's true, then write the loop
Binary searching on the answer means you have a predicate that's false for a while and then true forever:
f f f f f t t t t t
^ the answer
You're looking for the first t. So maintain exactly this invariant:
lois always a position that could still be the answerhiis one past the last candidate
int lo = 0, hi = n; // answer lives in [lo, hi)
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (ok(mid)) hi = mid; // mid works, so nothing past it matters
else lo = mid + 1; // mid fails, so the answer is strictly after
}
// lo == hi == first index where ok() is true
Two details that remove most of the pain:
lo + (hi - lo) / 2instead of(lo + hi) / 2— the second overflows once the bounds get nearINT_MAX.- The half-open range
[lo, hi)means the loop ends withlo == hiand no final "which one is it?" check.
The part people skip
ok() has to be monotone: once it's true it stays true. If it isn't, binary
search doesn't merely give a wrong answer, it gives a confidently wrong one.
Before writing the loop, say out loud why the predicate can't flip back. If you can't, the problem probably isn't a binary search.
Complexity
O(logn) calls to ok(). If ok() is itself O(n) — which it usually is
when you're binary searching on an answer — the total is O(nlogn), and
that's normally the intended solution.