LeetCopilot Logo
LeetCopilot
LeetCode Pattern/Binary Search/Binary Search on Answer: The Ultimate Guide to "Guess and Check" Optimization

Binary Search on Answer: The Ultimate Guide to "Guess and Check" Optimization

LeetCopilot Team
Dec 30, 2025
18 min read
Binary SearchBinary Search on AnswerOptimizationInterview PrepTemplates
Master the binary search on answer pattern used in optimization problems. Learn when to use it, how to identify answer spaces, design feasibility functions, and solve "minimize maximum" and "maximize minimum" problems with production-ready templates.

Binary search on answer is one of the most powerful and elegant problem-solving techniques in competitive programming and technical interviews. It transforms seemingly intractable optimization problems into efficient O(n log m) solutions.

But here's what makes it challenging: there's no explicit sorted array. Instead, you're searching on an answer space—a range of possible solutions—using a "guess and check" approach. Once you master this pattern, you'll unlock an entire class of problems that would otherwise seem impossible.

This comprehensive guide will teach you everything about binary search on answer: when to use it, how to identify the answer space, how to design feasibility functions, and complete templates for both "minimize maximum" and "maximize minimum" problems.

TL;DR

Use binary search on answer when:

  • Problem asks to "minimize the maximum" or "maximize the minimum"
  • Answer has a clear range [min, max]
  • You can write a feasibility function to check if a candidate answer works
  • Feasibility is monotonic (if x works, all values in one direction also work)

Template:

python
def binary_search_on_answer(min_val, max_val, is_feasible):
    left, right = min_val, max_val
    result = max_val
    
    while left <= right:
        mid = left + (right - left) // 2
        if is_feasible(mid):
            result = mid
            right = mid - 1  # Try smaller for "minimize"
        else:
            left = mid + 1
    
    return result

Time: O(log(max - min) × feasibility_check_time)

What Is Binary Search on Answer?

The Core Concept

Binary search on answer is a technique where you binary search on the range of possible answers rather than on an array of elements. You repeatedly "guess" a candidate answer and check if it's feasible.

The fundamental idea: If you can verify whether a candidate answer works, and feasibility is monotonic (if answer x works, then x+1 also works OR x-1 also works), you can binary search for the optimal answer.

Example:

code
Problem: Koko Eating Bananas
Piles: [3, 6, 7, 11], Hours: 8

Question: What's the minimum eating speed to finish all bananas?

Answer space: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
Feasibility:   F  F  F  T  T  T  T  T  T  T   T
                        ↑
                  Find first T (minimum feasible speed)

Speed 1: 3+6+7+11 = 27 hours > 8 ✗
Speed 2: 2+3+4+6 = 15 hours > 8 ✗
Speed 3: 1+2+3+4 = 10 hours > 8 ✗
Speed 4: 1+2+2+3 = 8 hours ≤ 8 ✓ (Answer!)

Classic binary search:

  • Searches in an explicit array
  • Looking for a specific element
  • Array must be sorted

Binary search on answer:

  • Searches in an implicit answer space (range of possible solutions)
  • Looking for the optimal value that satisfies a condition
  • Answer space must have monotonic feasibility

The "Guess and Check" Framework

The pattern follows three steps:

  1. Define the answer space: Determine the minimum and maximum possible answers
  2. Write a feasibility function: Check if a candidate answer works
  3. Binary search: Find the optimal answer (minimum or maximum feasible value)

Visual representation:

code
Answer Space: [min ..................... max]
Feasibility:  [F F F F F T T T T T T T T T T]
                         ↑
                    Find this boundary

Binary search finds the boundary between feasible and infeasible

When to Use Binary Search on Answer

Recognition Patterns

Use binary search on answer when you see these keywords:

"Minimize the maximum"

  • "Minimize the maximum load"
  • "Minimize the largest sum"
  • "Minimize the maximum distance"

"Maximize the minimum"

  • "Maximize the minimum distance"
  • "Maximize the smallest value"
  • "Maximize the minimum force"

"Find the smallest/largest value such that..."

  • "Find the smallest speed such that..."
  • "Find the largest capacity such that..."

Optimization with constraints

  • "What's the minimum X to achieve Y within Z constraint?"

The Three Requirements

Binary search on answer requires:

  1. Clear answer range: You can determine [min_answer, max_answer]
  2. Feasibility check: You can verify if a candidate answer works
  3. Monotonicity: If answer x works, then:
    • For "minimize maximum": all answers > x also work
    • For "maximize minimum": all answers < x also work

Example check:

code
Problem: Koko Eating Bananas

1. Answer range? ✓
   - Min: 1 banana/hour (slowest possible)
   - Max: max(piles) (eat entire largest pile in 1 hour)

2. Feasibility check? ✓
   - Given speed k, calculate hours = sum(ceil(pile/k))
   - Check if hours <= h

3. Monotonicity? ✓
   - If speed k works, any speed > k also works
   - We want minimum, so search for smallest feasible k

Decision Tree

code
Question 1: Does the problem ask for optimization?
├─ "Minimize maximum" or "Maximize minimum" → Continue
└─ Just "find" or "search" → Classic binary search

Question 2: Is there a clear answer range?
├─ Yes, I can define [min, max] → Continue
└─ No → Binary search on answer won't work

Question 3: Can I check if a candidate answer works?
├─ Yes, I can write is_feasible(x) → Continue
└─ No → Need different approach

Question 4: Is feasibility monotonic?
├─ If x works, does x+1 work? (or x-1?) → Binary search on answer ✓
└─ No monotonicity → Need exhaustive search

The Universal Template

Python Template

python
def binary_search_on_answer(min_answer, max_answer, is_feasible, minimize=True):
    """
    Template for binary search on answer.
    
    Args:
        min_answer: Minimum possible answer
        max_answer: Maximum possible answer
        is_feasible: Function that checks if a candidate answer works
        minimize: True for "minimize maximum", False for "maximize minimum"
    
    Returns:
        Optimal answer
    
    Time: O(log(max - min) × feasibility_check_time)
    Space: O(1)
    """
    left, right = min_answer, max_answer
    result = max_answer if minimize else min_answer
    
    while left <= right:
        mid = left + (right - left) // 2
        
        if is_feasible(mid):
            result = mid
            if minimize:
                # Try to find smaller feasible answer
                right = mid - 1
            else:
                # Try to find larger feasible answer
                left = mid + 1
        else:
            if minimize:
                # Need larger answer
                left = mid + 1
            else:
                # Need smaller answer
                right = mid - 1
    
    return result

JavaScript Template

javascript
function binarySearchOnAnswer(minAnswer, maxAnswer, isFeasible, minimize = true) {
    let left = minAnswer;
    let right = maxAnswer;
    let result = minimize ? maxAnswer : minAnswer;
    
    while (left <= right) {
        const mid = left + Math.floor((right - left) / 2);
        
        if (isFeasible(mid)) {
            result = mid;
            if (minimize) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        } else {
            if (minimize) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
    }
    
    return result;
}

Java Template

java
public int binarySearchOnAnswer(int minAnswer, int maxAnswer, 
                                 Predicate<Integer> isFeasible, 
                                 boolean minimize) {
    int left = minAnswer;
    int right = maxAnswer;
    int result = minimize ? maxAnswer : minAnswer;
    
    while (left <= right) {
        int mid = left + (right - left) / 2;
        
        if (isFeasible.test(mid)) {
            result = mid;
            if (minimize) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        } else {
            if (minimize) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
    }
    
    return result;
}

Pattern 1: Minimize the Maximum

Problem: Koko Eating Bananas (LeetCode #875)

Problem statement: Koko has piles of bananas. She can eat at most k bananas per hour. Find the minimum k such that she can finish all bananas within h hours.

Solution:

python
def minEatingSpeed(piles: List[int], h: int) -> int:
    """
    Find minimum eating speed to finish all bananas in h hours
    
    Time: O(n log m) where m = max(piles)
    Space: O(1)
    """
    def can_finish(speed):
        """Check if Koko can finish with given speed"""
        hours = 0
        for pile in piles:
            # Ceiling division: how many hours for this pile
            hours += (pile + speed - 1) // speed
        return hours <= h
    
    # Answer space: [1, max(piles)]
    # Min: 1 banana/hour (slowest)
    # Max: max(piles) (eat largest pile in 1 hour)
    return binary_search_on_answer(1, max(piles), can_finish, minimize=True)

# Example
print(minEatingSpeed([3, 6, 7, 11], 8))  # 4
# Speed 4: ceil(3/4) + ceil(6/4) + ceil(7/4) + ceil(11/4) = 1+2+2+3 = 8 ✓

Why it works:

  • If Koko can finish with speed k, she can finish with any speed > k (monotonic)
  • We want the minimum feasible speed
  • Binary search finds the smallest k where can_finish(k) == True

Step-by-step trace:

code
Piles: [3, 6, 7, 11], h = 8

left=1, right=11, mid=6
  can_finish(6)? 1+1+2+2=6 ≤ 8 ✓
  result=6, try smaller: right=5

left=1, right=5, mid=3
  can_finish(3)? 1+2+3+4=10 > 8 ✗
  Need larger: left=4

left=4, right=5, mid=4
  can_finish(4)? 1+2+2+3=8 ≤ 8 ✓
  result=4, try smaller: right=3

left=4, right=3 → stop
Answer: 4

Problem: Capacity To Ship Packages (LeetCode #1011)

Problem statement: Ship packages within d days. Each day, load packages in order up to ship capacity. Find minimum capacity.

Solution:

python
def shipWithinDays(weights: List[int], days: int) -> int:
    """
    Find minimum ship capacity to ship all packages in given days
    
    Time: O(n log(sum - max))
    Space: O(1)
    """
    def can_ship(capacity):
        """Check if we can ship with given capacity"""
        days_needed = 1
        current_load = 0
        
        for weight in weights:
            if current_load + weight > capacity:
                # Start new day
                days_needed += 1
                current_load = weight
            else:
                current_load += weight
        
        return days_needed <= days
    
    # Answer space: [max(weights), sum(weights)]
    # Min: max(weights) (must fit largest package)
    # Max: sum(weights) (ship everything in 1 day)
    return binary_search_on_answer(max(weights), sum(weights), can_ship)

# Example
print(shipWithinDays([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 5))  # 15

Why it works:

  • If capacity c works, any capacity > c also works (monotonic)
  • We want minimum feasible capacity
  • Greedy loading: load packages until capacity is exceeded, then start new day

Problem: Split Array Largest Sum (LeetCode #410)

Problem statement: Split array into m subarrays. Minimize the largest sum among these subarrays.

Solution:

python
def splitArray(nums: List[int], m: int) -> int:
    """
    Split array into m subarrays, minimize largest sum
    
    Time: O(n log(sum - max))
    Space: O(1)
    """
    def can_split(max_sum):
        """Check if we can split into m subarrays with max sum"""
        subarrays = 1
        current_sum = 0
        
        for num in nums:
            if current_sum + num > max_sum:
                # Start new subarray
                subarrays += 1
                current_sum = num
            else:
                current_sum += num
        
        return subarrays <= m
    
    # Answer space: [max(nums), sum(nums)]
    # Min: max(nums) (each element in its own subarray)
    # Max: sum(nums) (all elements in one subarray)
    return binary_search_on_answer(max(nums), sum(nums), can_split)

# Example
print(splitArray([7, 2, 5, 10, 8], 2))  # 18
# Split: [7, 2, 5] (sum=14) and [10, 8] (sum=18), max=18

Pattern 2: Maximize the Minimum

Problem: Magnetic Force Between Two Balls (LeetCode #1552)

Problem statement: Place m balls in n positions to maximize the minimum distance between any two balls.

Solution:

python
def maxDistance(position: List[int], m: int) -> int:
    """
    Maximize minimum distance between m balls
    
    Time: O(n log n + n log(max - min))
    Space: O(1)
    """
    position.sort()
    
    def can_place(min_dist):
        """Check if we can place m balls with minimum distance"""
        count = 1  # Place first ball at position[0]
        last_pos = position[0]
        
        for pos in position[1:]:
            if pos - last_pos >= min_dist:
                count += 1
                last_pos = pos
                if count == m:
                    return True
        
        return count >= m
    
    # Answer space: [1, position[-1] - position[0]]
    # Min: 1 (minimum possible distance)
    # Max: max distance between first and last position
    return binary_search_on_answer(
        1, 
        position[-1] - position[0], 
        can_place, 
        minimize=False  # Maximize
    )

# Example
print(maxDistance([1, 2, 3, 4, 7], 3))  # 3
# Place at positions 1, 4, 7: distances are 3, 3

Why it works:

  • If minimum distance d works, any distance < d also works (monotonic)
  • We want maximum feasible distance
  • Greedy placement: place balls as far apart as possible

Problem: Aggressive Cows (Classic Problem)

Problem statement: Place c cows in n stalls to maximize the minimum distance between any two cows.

Solution:

python
def aggressive_cows(stalls: List[int], cows: int) -> int:
    """
    Maximize minimum distance between cows
    
    Time: O(n log n + n log(max - min))
    Space: O(1)
    """
    stalls.sort()
    
    def can_place(min_dist):
        """Check if we can place cows with minimum distance"""
        count = 1
        last_pos = stalls[0]
        
        for stall in stalls[1:]:
            if stall - last_pos >= min_dist:
                count += 1
                last_pos = stall
                if count == cows:
                    return True
        
        return False
    
    return binary_search_on_answer(
        1,
        stalls[-1] - stalls[0],
        can_place,
        minimize=False
    )

# Example
print(aggressive_cows([1, 2, 4, 8, 9], 3))  # 3
# Place at 1, 4, 8: distances are 3, 4

How to Identify the Answer Space

Step 1: Determine Minimum Possible Answer

Common patterns:

  • Speed/rate problems: 1 (minimum speed)
  • Capacity problems: max(array) (must fit largest element)
  • Distance problems: 1 (minimum distance)
  • Sum problems: max(array) (minimum possible maximum sum)

Example:

code
Koko Eating Bananas:
  Min speed = 1 (slowest possible)

Ship Packages:
  Min capacity = max(weights) (must fit largest package)

Magnetic Force:
  Min distance = 1 (minimum possible distance)

Step 2: Determine Maximum Possible Answer

Common patterns:

  • Speed/rate problems: max(array) or total/time
  • Capacity problems: sum(array) (fit everything at once)
  • Distance problems: max_position - min_position
  • Sum problems: sum(array) (all elements together)

Example:

code
Koko Eating Bananas:
  Max speed = max(piles) (eat largest pile in 1 hour)

Ship Packages:
  Max capacity = sum(weights) (ship everything in 1 day)

Magnetic Force:
  Max distance = position[-1] - position[0]

Step 3: Verify Monotonicity

For "minimize maximum":

  • If answer x works, does x+1 also work? → Should be YES
  • We're finding the minimum feasible value

For "maximize minimum":

  • If answer x works, does x-1 also work? → Should be YES
  • We're finding the maximum feasible value

Example:

code
Koko Eating Bananas (minimize maximum):
  If speed 5 works, does speed 6 work? YES (faster is always ok)
  Monotonicity: [F F F F T T T T T T T]
                         ↑ find first T

Magnetic Force (maximize minimum):
  If distance 3 works, does distance 2 work? YES (smaller is easier)
  Monotonicity: [T T T T T F F F F F F]
                         ↑ find last T

Feasibility Function Design

The Three Components

Every feasibility function has:

  1. Initialize state: Set up counters/accumulators
  2. Iterate through data: Process each element
  3. Check constraint: Return true/false based on condition

Template:

python
def is_feasible(candidate_answer):
    # 1. Initialize
    counter = initial_value
    
    # 2. Iterate
    for item in data:
        # Update counter based on candidate_answer
        counter = update(counter, item, candidate_answer)
    
    # 3. Check constraint
    return counter meets_constraint

Common Patterns

Pattern 1: Counting (Koko Eating Bananas)

python
def can_finish(speed):
    hours = 0
    for pile in piles:
        hours += (pile + speed - 1) // speed  # Ceiling division
    return hours <= h

Pattern 2: Greedy Grouping (Ship Packages)

python
def can_ship(capacity):
    days = 1
    current_load = 0
    for weight in weights:
        if current_load + weight > capacity:
            days += 1
            current_load = weight
        else:
            current_load += weight
    return days <= max_days

Pattern 3: Greedy Placement (Magnetic Force)

python
def can_place(min_dist):
    count = 1
    last_pos = positions[0]
    for pos in positions[1:]:
        if pos - last_pos >= min_dist:
            count += 1
            last_pos = pos
    return count >= m

Common Mistakes

Mistake 1: Wrong Monotonicity Direction

Wrong:

python
# For "minimize maximum", checking if we can do BETTER than mid
if is_feasible(mid):
    left = mid + 1  # WRONG: should try smaller

Correct:

python
if is_feasible(mid):
    result = mid
    right = mid - 1  # Try smaller for minimize

See guide: Feasibility Function Mistakes

Mistake 2: Off-by-One in Counting

Wrong:

python
hours += pile // speed  # WRONG: doesn't handle remainder

Correct:

python
hours += (pile + speed - 1) // speed  # Ceiling division
# Or: hours += math.ceil(pile / speed)

Mistake 3: Incorrect Greedy Logic

Wrong:

python
# Placing balls: forgetting to update last position
if pos - last_pos >= min_dist:
    count += 1
    # WRONG: didn't update last_pos

Correct:

python
if pos - last_pos >= min_dist:
    count += 1
    last_pos = pos  # Update position

Practice Problems

Master binary search on answer with these problems:

Beginner:

  1. Koko Eating Bananas (#875) — Classic minimize maximum
  2. Capacity To Ship Packages (#1011) — Greedy grouping
  3. Find the Smallest Divisor (#1283) — Similar to Koko

Intermediate:
4. Split Array Largest Sum (#410) — Minimize maximum sum
5. Magnetic Force Between Two Balls (#1552) — Maximize minimum
6. Minimize Max Distance to Gas Station (#774) — Continuous answer space
7. Kth Smallest Element in Sorted Matrix (#378) — Count elements ≤ mid

Advanced:
8. Median of Two Sorted Arrays (#4) — Binary search on answer + partitioning
9. Minimize Max Distance to Gas Station (#774) — Floating point binary search
10. Cutting Ribbons (#1891) — Maximize with constraint

Complexity Analysis

Time Complexity: O(log(max - min) × C)

  • log(max - min): Binary search iterations on answer space
  • C: Cost of feasibility check (usually O(n))

Examples:

  • Koko Eating Bananas: O(n log m) where m = max(piles)
  • Ship Packages: O(n log(sum - max))
  • Magnetic Force: O(n log n + n log(max - min)) — sorting + binary search

Space Complexity: O(1)

  • Only uses constant extra space for variables

FAQ

Q: How is this different from regular binary search?

A: Regular binary search searches in an explicit sorted array. Binary search on answer searches in an implicit answer space (range of possible solutions). The key is monotonic feasibility, not a sorted array.

Q: How do I know if feasibility is monotonic?

A: Ask: "If answer x works, does x+1 work (or x-1)?" If yes, it's monotonic. For "minimize maximum," larger values should work if smaller ones do. For "maximize minimum," smaller values should work if larger ones do.

Q: What if I can't determine the answer space?

A: Look for natural bounds:

  • Speed: [1, max_value]
  • Capacity: [max_element, sum_all]
  • Distance: [1, max_distance]
    If bounds are unclear, binary search on answer may not apply.

Q: Can the answer space be floating point?

A: Yes! Use a precision threshold instead of left <= right:

python
while right - left > 1e-6:
    mid = (left + right) / 2
    if is_feasible(mid):
        right = mid
    else:
        left = mid

Q: What if my feasibility check is O(n²)?

A: Binary search on answer will be O(n² log m), which may still be acceptable depending on constraints. Optimize the feasibility check if possible.

Conclusion

Binary search on answer is a powerful technique that transforms optimization problems into efficient logarithmic solutions. It's not about searching in arrays—it's about searching in answer spaces.

Key principles:

  • Identify the pattern: "Minimize maximum" or "maximize minimum"
  • Define answer space: [min_answer, max_answer]
  • Check monotonicity: If x works, does x±1 work?
  • Write feasibility function: Can candidate answer satisfy constraints?
  • Binary search: Find optimal boundary between feasible and infeasible

The template:

python
def solve(data, constraint):
    def is_feasible(candidate):
        # Check if candidate answer works
        return check_constraint(candidate)
    
    return binary_search_on_answer(min_val, max_val, is_feasible)

When to use:

  • Optimization problems with clear answer range
  • Monotonic feasibility
  • Can verify candidate answers efficiently

Master this pattern, and you'll solve dozens of LeetCode hard problems with confidence. For more patterns, see the Complete Binary Search Guide, Why Binary Search on Answer Works, and Minimize Maximum vs Maximize Minimum.

Next time you see "minimize the maximum" or "maximize the minimum," reach for binary search on answer.

Want to Practice LeetCode Smarter?

LeetCopilot is a free browser extension that enhances your LeetCode practice with AI-powered hints, personalized study notes, and realistic mock interviews — all designed to accelerate your coding interview preparation.

Also compatible with Edge, Brave, and Opera

Related Tutorials