DSA

Advanced Binary Search on Answer in Java - Interview Preparation Guide

6 min read Updated Mar 27, 2026

Monotonic Feasibility Optimization

Advanced binary search on answer is the optimization pattern for numeric decision spaces where feasibility is monotonic but the helper is non-trivial. Strong candidates separate the two responsibilities cleanly: prove monotonicity first, then make the helper efficient enough for the outer binary search to be worthwhile.

Interview lens

A strong explanation should name the invariant, the safe transition, and the condition that makes this pattern preferable to brute force.

Pattern Summary Table

Pattern When to Use Key Idea Example
04 23 Binary Search On Answer Advanced the answer is numeric and can be tested by a monotonic feasibility function search the first valid answer instead of scanning every candidate Split Array Largest Sum

Problem Statement

Given a numeric answer space with a yes/no feasibility test, find the smallest or largest valid answer faster than trying every candidate.

Note

Emphasize the constraints before coding. The real signal is often whether the brute-force search space, update volume, or graph model makes the naive solution impossible.

Pattern Recognition Signals

  • Keywords in the problem: minimum feasible, maximum possible, can(mid), monotonic helper.
  • Structural signal: once an answer works, all larger or smaller answers on one side also work.
  • Complexity signal: the optimized version avoids repeated rescans, recomputation, or state explosion that brute force would suffer.

Important

If you can write a monotonic feasibility helper over an ordered answer space, think binary search on answer.

Java Template

int lo = 1, hi = 1_000_000_000;
while (lo < hi) {
    int mid = lo + (hi - lo) / 2;
    if (feasible(mid)) hi = mid;
    else lo = mid + 1;
}

Dry Run (Conceptual)

Suppose feasible threshold starts from x >= 7. Search range [1..10]:

  1. mid=5 -> not feasible => lo=6
  2. mid=8 -> feasible => hi=8
  3. mid=7 -> feasible => hi=7
  4. mid=6 -> not feasible => lo=7

Stop at lo=hi=7 (minimum feasible answer).


Monotonic Predicate Requirement

This pattern only works if predicate is monotonic:

  • all false then true (FFFFTTTT), or
  • all true then false (TTTTFFFF)

If feasibility oscillates, binary search on answer is invalid.


Bound Initialization Tips

  • lo should be guaranteed invalid or minimum candidate
  • hi should be guaranteed valid (for min-feasible search)

Good bounds reduce bugs and iterations. For some problems, derive bounds from input (max element, sum, etc.) instead of fixed constants.


Problem 1: Koko Eating Bananas

Problem description: Given banana piles and h hours, return the minimum integer eating speed that lets Koko finish in time.

What we are solving actually: We are not searching over pile positions. We are searching over candidate answers, and feasibility is monotonic: if a speed works, any larger speed also works.

What we are doing actually:

  1. Binary-search the speed range from 1 to max(pile).
  2. Check whether a candidate speed finishes within h hours.
  3. Move left when the speed is feasible.
  4. Move right when the speed is too slow.
public int minEatingSpeed(int[] piles, int h) {
    int left = 1, right = 0;
    for (int pile : piles) right = Math.max(right, pile);

    while (left < right) {
        int mid = left + (right - left) / 2;
        if (canFinish(piles, h, mid)) {
            right = mid; // mid works, so keep searching for a smaller feasible answer.
        } else {
            left = mid + 1; // mid is too slow, so the answer must be larger.
        }
    }
    return left;
}

private boolean canFinish(int[] piles, int h, int speed) {
    long hours = 0;
    for (int pile : piles) {
        hours += (pile + speed - 1) / speed; // Ceiling division gives hours spent on this pile.
        if (hours > h) return false;
    }
    return true;
}

Debug steps:

  • print left, mid, right, and the computed hours each iteration
  • test a case where the answer is exactly 1 and one where it is max(pile)
  • verify the invariant that the true answer always stays inside the current search interval

Problem-Fit Checklist

  • Identify whether input size or query count requires preprocessing or specialized data structures.
  • Confirm problem constraints (sorted input, non-negative weights, DAG-only, immutable array, etc.).
  • Validate that the pattern gives asymptotic improvement over brute-force under worst-case input.
  • Define explicit success criteria: value only, index recovery, count, path reconstruction, or ordering.

Invariant and Reasoning

  • Write one invariant that must stay true after every transition (loop step, recursion return, or update).
  • Ensure each step makes measurable progress toward termination.
  • Guard boundary states explicitly (empty input, singleton, duplicates, overflow, disconnected graph).
  • Add a quick correctness check using a tiny hand-worked example before coding full solution.

Complexity and Design Notes

  • Compute time complexity for both preprocessing and per-query/per-update operations.
  • Track memory overhead and object allocations, not only Big-O notation.
  • Prefer primitives and tight loops in hot paths to reduce GC pressure in Java.
  • If multiple variants exist, choose the one with the simplest correctness proof first.

Production Perspective

  • Convert algorithmic states into explicit metrics (queue size, active nodes, cache hit ratio, relaxation count).
  • Add guardrails for pathological inputs to avoid latency spikes.
  • Keep implementation deterministic where possible to simplify debugging and incident analysis.
  • Separate pure algorithm logic from I/O and parsing so the core stays testable.

Implementation Workflow

  1. Implement the minimal correct template with clear invariants.
  2. Add edge-case tests before optimizing.
  3. Measure complexity-sensitive operations on realistic input sizes.
  4. Refactor for readability only after behavior is locked by tests.

Common Mistakes

  1. Choosing the pattern without proving problem fit.
  2. Ignoring edge cases (empty input, duplicates, overflow, disconnected state).
  3. Mixing multiple strategies without clear invariants.
  4. No complexity analysis against worst-case input.

  1. Koko Eating Bananas (LC 875)
    LeetCode
  2. Capacity To Ship Packages (LC 1011)
    LeetCode
  3. Split Array Largest Sum (LC 410)
    LeetCode

Key Takeaways

  • This pattern is most effective when transitions are explicit and invariants are enforced at every step.
  • Strong preconditions and boundary handling make these implementations production-safe.
  • Reuse this template and adapt it per problem constraints.

Categories

Tags

Continue reading

Previous Difference Array Range Update Pattern in Java - Interview Preparation Guide