Capacity To Ship Packages Within D Days

Binary search on the ship capacity itself: a greedy pass counts the days a capacity needs, and more capacity never needs more days.

Time O(n log(sum))Space O(1)Code C#
Watch it animatedStep through it, with the running line highlighted. Free with an account.

The idea

The answer lies between the heaviest package (anything smaller cannot carry it) and the total weight (one day carries everything). For a given capacity, loading greedily in order (keep adding until the next package would not fit, then start a new day) uses the fewest days possible. A bigger ship never needs more days, so the capacities split into "too small" then "big enough", and binary search finds the first big-enough one.

Code

public int ShipWithinDays(int[] weights, int days) {
    int lo = weights.Max(), hi = weights.Sum();
    while (lo < hi) {
        int cap = lo + (hi - lo) / 2;
        if (DaysNeeded(weights, cap) <= days) hi = cap;
        else lo = cap + 1;
    }
    return lo;
}

static int DaysNeeded(int[] weights, int cap) {
    int days = 1, load = 0;
    foreach (int w in weights) {
        if (load + w > cap) { days++; load = 0; } // ship is full: w waits for the next day
        load += w;
    }
    return days;
}

Tips

In the .NET library

weights.Max() and weights.Sum() need using System.Linq. Enumerable.Sum on int[] throws OverflowException rather than wrapping, so for huge inputs sum into a long.