DSA Roadmap/Binary Search

Binary Search on the Answer Space

Recognize the 'minimize the maximum / maximize the minimum' phrasing that signals binary search over a range of candidate answers, not array indices.

!!3/5Theory: 2h9 problems

The pattern behind the phrase

"Binary search on the answer" is the single most common disguised application of binary search in interviews, and it's where candidates who only memorized the sorted-array template get stuck — there's no array to search at all. Instead, you binary search over the space of possible answers (a range of numbers), using a feasibility check to decide which half of that range can be discarded.

The giveaway phrasing, almost verbatim, is:

  • "Minimize the maximum [something]" (e.g., minimize the largest sum among k subarrays)
  • "Maximize the minimum [something]" (e.g., maximize the smallest distance between chosen points)
  • "Find the minimum/smallest X such that [condition] is achievable"
  • "Find the maximum/largest X such that [condition] still holds"

Whenever you see this shape, stop thinking about the input's structure and start thinking about the answer's structure: is there a value x such that everything ≥ x (or ≤ x) is achievable, and everything on the other side isn't? If so, that's a monotonic predicate over the answer space, and you can binary search on it — this is exactly the generalization the Binary Search Fundamentals subtopic sets up.

The two-part recipe

  1. Define the search space. Pick lo and hi such that the true answer is guaranteed to lie in [lo, hi]. lo is usually the most conservative/smallest conceivable answer (often 1 or min(array)); hi is usually the worst-case brute-force answer (often sum(array) or max(array)).
  2. Define feasible(x): a monotonic boolean check. It must answer "if the answer were x, would this be achievable?" in a way that flips exactly once as x increases across the search space. This check is frequently a greedy simulation — see the Greedy topic for more on that mindset — that runs in O(n) or O(n log n).

Once both exist, the binary search itself is mechanical: it's the same lower-bound template from Binary Search Fundamentals, just applied to feasible(x) instead of an array index.

# Generic skeleton: minimize x such that feasible(x) is True # (works whenever feasibility is monotonic: False False ... False True True ... True) def minimize_feasible(lo, hi, feasible): while lo < hi: mid = lo + (hi - lo) // 2 if feasible(mid): hi = mid # mid works — a smaller x might also work, keep searching left else: lo = mid + 1 # mid doesn't work — the answer must be strictly larger return lo # smallest x for which feasible(x) is True # Generic skeleton: maximize x such that feasible(x) is True # (feasibility is now True True ... True False False ... False) def maximize_feasible(lo, hi, feasible): while lo < hi: mid = lo + (hi - lo + 1) // 2 # round UP — required to avoid an infinite loop if feasible(mid): lo = mid # mid works — try to push the answer even higher else: hi = mid - 1 # mid fails — the answer must be strictly smaller return lo # largest x for which feasible(x) is True

The rounding direction ((hi - lo) // 2 vs (hi - lo + 1) // 2) is the part people get wrong under pressure. The rule: whichever branch sets lo = mid (keeps mid as a candidate while moving the lower bound) must round mid up, or the search can get stuck with mid == lo forever when hi == lo + 1.

"Minimize the max" vs "maximize the min" — same skeleton, opposite direction

AspectMinimize the maximumMaximize the minimum
Typical phrasing"minimum capacity/speed/largest-subarray-sum such that ≤ some constraint""maximum smallest-gap/minimum-distance such that ≥ some constraint"
Direction of feasibleTrue for large x, False for small xTrue for small x, False for large x
Which bound moves on successhi = midlo = mid
mid roundingRound down (// 2)Round up ((... + 1) // 2)
Canonical shape"Can we finish within these constraints if the cap is x?""Can we still satisfy the constraint if the minimum allowed gap is x?"

Proving monotonicity out loud

Don't just assert the predicate is monotonic — say why. The standard argument: "if feasible(x) is true, is feasible(x + 1) (or x - 1) also true?" For a capacity/speed-style problem, a larger capacity can only make packing easier, never harder, which is the monotonicity proof in one sentence. Interviewers at a Senior bar want to hear this justification before you start coding, not just a working binary search that happens to pass.

Complexity analysis

Total complexity is not simply O(log n)** — it's:

O(log(hi - lo) × cost of feasible(x))

If feasible does a single O(n) pass (the common case — a greedy scan or count), the total is O(n log(range)), where range is hi - lo, not the input size. This distinction matters: on Koko Eating Bananas-style problems, range is bounded by max(piles), which can be far larger than n, so always state both bounds explicitly. Space is typically O(1) beyond whatever feasible itself allocates.

Common pitfalls

  • Wrong search space bounds. If lo is too large or hi too small, the true answer is excluded before the search even starts — always double check the extremes (lo = 1 or lo = min(...), hi = the "obviously always works" brute-force value).
  • Non-monotonic predicate. If you can't argue monotonicity in one sentence, binary search doesn't apply — you likely need a different technique (often Dynamic Programming or Greedy directly).
  • Off-by-one on inclusive vs. exclusive answer ranges, same failure mode as in Binary Search Fundamentals — pick [lo, hi] closed and be consistent about which branch owns mid.
  • Integer/real-valued confusion. Everything above assumes a discrete (integer) answer space with a finite loop bound. If a problem's answer space is continuous (real-valued), you cannot loop until lo == hi — instead iterate a fixed number of times (~100 iterations of halving is far more than enough precision for any float tolerance you'll see in an interview) or loop while hi - lo > epsilon.
  • Expensive feasibility checks. If feasible(x) is itself O(n log n) or worse, the compounded complexity can exceed what naive approaches would cost — always sanity-check the full bound against the problem's constraints before committing to this approach out loud.

Where this shows up later

This is the most "portable" idea in the entire roadmap: you will see the same two-step recipe (define a search space over answers, define a monotonic feasibility check) resurface as an optimization on top of Dynamic Programming solutions (replacing an O(n²) DP dimension with an O(n log n) binary search), inside Greedy problems where the feasibility check is the greedy algorithm, and even in some Graph shortest-path variants ("minimize the maximum edge weight on a path" — a direct binary-search-on-answer formulation). Once you can spot the phrasing, you'll start seeing it everywhere.

Further Resources (Optional)

Practice Problems

Interview relevancy:!!!Critical — must-have!!Important — highly recommended!Good to have~Niche — rarely asked

Optional Practice (Extra Reps)

For once you've cleared the main set above and want more reps on this pattern. These don't count toward the roadmap's progress stats — solve them purely for your own benefit.