Capacity to Ship Packages Within D Days
Capacity to Ship Packages Within D Days: packages must ship in their given order. Each day the ship loads packages in sequence without exceeding its capacity. Find the minimum capacity that ships everything within days days.
- 1 <= days <= weights.length <= 5 * 10⁴
- 1 <= weights[i] <= 500
Intuition
Capacity to ship packages within d days finds the smallest ship capacity that delivers all packages, in their given order, within days days. Nothing here looks like a search problem at first — but the structure of the answer is what gives it away.
Consider what happens as capacity grows. A larger ship never needs more days, and a smaller one never needs fewer. So the predicate "can this capacity finish in time?" is false for small capacities and true for large ones, flipping exactly once:
- The feasibility of a capacity is monotonic, which is precisely what binary search requires — even though the input array is not sorted.
This is binary search on the answer rather than on the array, and the array's order must be preserved, so sorting it would be wrong.
The search bounds come from the problem's own constraints. The lower bound is max(weights), since a ship smaller than the heaviest package can never carry it. The upper bound is sum(weights), which ships everything in a single day. Starting the lower bound at 1 produces an infeasible answer, because the simulation would never fit the heaviest item.
The feasibility check is a simple greedy: accumulate weights into the current day until adding the next would exceed capacity, then start a new day. Loading as much as possible each day is optimal, since packages must ship in order and delaying one never helps.
When a capacity is feasible, record it and search lower; otherwise search higher. The loop converges on the smallest feasible value.
Koko Eating Bananas and Split Array Largest Sum are the same technique with a different feasibility check.
Binary search on the answer again, with the interesting part being the bounds. The capacity can't be below max(weights) — a single package must fit — and never needs to exceed sum(weights), which ships everything in one day. Deriving tight bounds from the problem's physics is half the work.
Approach
Before reading on: price up what the direct approach costs here, then ask what property lets you throw away half the range after one comparison. Aim for O(n log sum(weights)) time and O(1) space.
Spot the monotonic predicate
A larger capacity never needs more days. Feasibility is false then true, flipping exactly once — the condition binary search needs, even though the array itself is unsorted.
Search the answer, not the array
Binary search runs over candidate capacities rather than over the weights. The array's order must be preserved, so sorting it would break the problem.
Set the bounds from the constraints
The lower bound is max(weights) — a smaller ship cannot carry the heaviest package. The upper bound is sum(weights), which ships everything in one day. Starting at 1 yields an infeasible answer.
Write the greedy feasibility check
Accumulate weights into the current day until adding the next would exceed capacity, then start a new day. Loading maximally is optimal, since order is fixed and delaying never helps.
Narrow toward the smallest feasible value
When a capacity finishes within days, record it and search lower; otherwise search higher. The loop converges on the minimum workable capacity.
Recognise the wider pattern
Koko Eating Bananas and Split Array Largest Sum use the same structure with a different check. Naming the pattern turns several problems into one technique.
Cost of the search
Each feasibility check is O(n) and the range halves each step, giving O(n log(sum − max)) time and O(1) space.
Solution & live demo
Common pitfalls
Starting lo at 1
lo, hi = 1, sum(weights)
lo, hi = max(weights), sum(weights)
Packages can't be split, so any capacity below the heaviest one makes the problem unsolvable — the greedy check would loop forever or silently miscount. max(weights) is the smallest feasible capacity.
Starting the day counter at 0
used, load = 0, 0
used, load = 1, 0
You're already on day one before loading anything. Counting from 0 reports one fewer day than reality and accepts capacities that miss the deadline by exactly one day.
Resetting load to 0 instead of w when a new day starts
used += 1 load = 0
used += 1 load = w
The package that triggered the new day still has to be shipped — on that new day. Setting load = 0 drops it entirely, so the check reports fewer days than the plan really needs.
Edge cases
The answer is sum(weights) — the top of the search range. Every smaller capacity needs at least two days.
Each package gets its own day, so the answer is max(weights) — the bottom of the range.
It alone forces the lower bound. The search cannot return anything below it, which is exactly why the range starts at max(weights).
The extra days are simply unused; the answer is still max(weights).