Skip to content
article

Binary search on the answer: when nothing is sorted but you can still binary search

Ship packages in D days, Koko eating bananas, aggressive cows. The array is not sorted. The answer space is.

Nikhil Sharan@nikhil_twopointers

August 28, 2026 · 4 min read

Students learn binary search as "find x in a sorted array" and then get stuck on questions where nothing is sorted. The trick is that you are not searching the array. You are searching the answer.

The problem

You have packages with weights w[i] that must be shipped in order. A ship carries them over D days, loading packages in order each day until the next one would exceed its capacity. What is the minimum capacity that ships everything within D days?

Brute force

The capacity is at least max(w) (the heaviest package must fit) and at most sum(w) (ship everything on day 1). Try every capacity from max to sum, simulate, return the first that works. With sum up to 2.5 × 10^7 that is far too slow.

The observation

If capacity c works, then c + 1 also works. A bigger ship never needs more days. So the answers look like this:

capacity:  4  5  6  7  8  9  10 ...
works?     F  F  T  T  T  T  T  ...

That is a sorted array of booleans. Find the first T. That is binary search. The only thing you need is a function feasible(c) that answers yes or no in O(n).

bool canShip(const vector<int>& w, int days, long long cap) {
    int used = 1;
    long long load = 0;
    for (int x : w) {
        if (load + x > cap) { used++; load = 0; }
        load += x;
    }
    return used <= days;
}

int shipWithinDays(vector<int>& w, int days) {
    long long lo = *max_element(w.begin(), w.end());
    long long hi = accumulate(w.begin(), w.end(), 0LL);
    while (lo < hi) {
        long long mid = lo + (hi - lo) / 2;
        if (canShip(w, days, mid)) hi = mid;   // mid works, maybe something smaller works too
        else lo = mid + 1;                     // mid fails, answer is bigger
    }
    return (int)lo;
}

Dry run

w = [3, 2, 2, 4, 1, 4], days = 3. lo = 4, hi = 16.

  • mid = 10: [3,2,2] [4,1,4] = 2 days. Works, hi = 10.
  • mid = 7: [3,2,2] [4,1] [4] = 3 days. Works, hi = 7.
  • mid = 5: [3,2] [2] [4,1] [4] = 4 days. Fails, lo = 6.
  • mid = 6: [3,2] [2,4] [1,4] = 3 days. Works, hi = 6.

lo == hi == 6. Answer 6.

How to recognise it

  • "Minimize the maximum" or "maximize the minimum"
  • "What is the smallest X such that you can finish within D days / K workers / H hours"
  • Values up to 10^9, so you cannot loop over every candidate
  • You can write the yes/no check in O(n) or O(n log n)

The three bugs everybody makes

  1. Wrong bounds. Starting lo at 1 instead of max(w) makes the check do strange things. Think about what the smallest possible answer is.
  2. Overflow. Sums of 10^5 values up to 10^9 do not fit in int. long long, always.
  3. Infinite loop on max-of-min questions. In aggressive cows you search for the largest value that works, so the update becomes lo = mid. With mid rounded down and lo + 1 == hi, lo never moves. Use mid = lo + (hi - lo + 1) / 2 there.

Same pattern: Koko eating bananas (search the speed), split array largest sum (literally this question in disguise), minimum days to make m bouquets, aggressive cows / magnetic force between balls (maximize the minimum).

Time: O(n log(sum)). For n = 5 × 10^4 and sum around 2.5 × 10^7, that is about 25 checks of 5 × 10^4 each, roughly 1.25 million operations. Space: O(1).

Written by

Nikhil Sharan

I teach DSA and system design on YouTube (Two Pointers, 1.2M). Ex-SDE at two product companies, now teaching full time. Dry run everything. No paid course here, only free stuff and honest opinions.

Get the best of #compiling weekly

One email each Monday with the most useful posts. No spam; unsubscribe in one click.

Comments

9

Sign in to join the conversation.

Sign in to comment
Sneha Kulkarni@laidoff_not_out2 rep in Compiling
ok this one is going in the notes. "feasible(x) is monotonic" is the sentence i was missing for 3 days on koko bananas
7 net votes
Kunal Bhatia@kunal_dsa2 rep in Compiling
The lo = mid infinite loop on max-of-min questions cost me an onsite in 2022. Froze on the whiteboard and the interviewer just watched. Bhai kya hi bolu.
4 net votes
Nikhil Sharan@nikhil_twopointers#1 in Compiling
Everyone has one of those. The rule I give students: if you write lo = mid anywhere, round mid up. Write it at the top of the page before you start.
1 net votes
Ankit Khurana@faang_or_bust2 rep in Compiling
aggressive cows is the real test here. ship packages is leetcode medium marketing
3 net votes
Grace Wanjiru@grace_wanjiru1 rep in Compiling
I teach a Python class in Nairobi and I'm stealing the "smallest X such that" signal list, with credit. One note for Python folks: the bisect module won't help much here, you write the loop yourself, which is honestly a good thing for learning.
4 net votes
Danny Cho@danny_cho_la1 rep in Compiling
Real-world cousin of this: capacity planning. "What's the smallest instance count that keeps p99 under 200ms" is binary search with a load test as the feasibility check. Very expensive check, same idea.
6 net votes
Nikhil Sharan@nikhil_twopointers#1 in Compiling
Beautiful example. That goes into the next version of this post, thank you Danny.
8 net votes
Kelly Zhao@kel_zhao1 rep in Compiling
this exact pattern was in my co-op OA last term, minimize max load across servers. passed bc i'd seen this kind of post ngl 🪿
5 net votes
Mahin Hasan@mahin_cp1 rep in Compiling
solid. on CF this is a 1400-1600 trick, "binary search the answer + greedy check". tip: even when check() is O(n log n) it's still fine, people overthink
5 net votes