Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

1011. Capacity To Ship Packages Within D Days - Leetcode Solution

Code Implementation

class Solution:
    def shipWithinDays(self, weights, D):
        def canShip(capacity):
            days = 1
            total = 0
            for w in weights:
                if total + w > capacity:
                    days += 1
                    total = 0
                total += w
            return days <= D

        left, right = max(weights), sum(weights)
        while left < right:
            mid = (left + right) // 2
            if canShip(mid):
                right = mid
            else:
                left = mid + 1
        return left
      
class Solution {
public:
    bool canShip(vector<int>& weights, int D, int capacity) {
        int days = 1, total = 0;
        for (int w : weights) {
            if (total + w > capacity) {
                days++;
                total = 0;
            }
            total += w;
        }
        return days <= D;
    }
    int shipWithinDays(vector<int>& weights, int D) {
        int left = *max_element(weights.begin(), weights.end());
        int right = accumulate(weights.begin(), weights.end(), 0);
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (canShip(weights, D, mid))
                right = mid;
            else
                left = mid + 1;
        }
        return left;
    }
};
      
class Solution {
    public int shipWithinDays(int[] weights, int D) {
        int left = 0, right = 0;
        for (int w : weights) {
            left = Math.max(left, w);
            right += w;
        }
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (canShip(weights, D, mid)) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return left;
    }
    private boolean canShip(int[] weights, int D, int capacity) {
        int days = 1, total = 0;
        for (int w : weights) {
            if (total + w > capacity) {
                days++;
                total = 0;
            }
            total += w;
        }
        return days <= D;
    }
}
      
var shipWithinDays = function(weights, D) {
    function canShip(capacity) {
        let days = 1, total = 0;
        for (let w of weights) {
            if (total + w > capacity) {
                days++;
                total = 0;
            }
            total += w;
        }
        return days <= D;
    }

    let left = Math.max(...weights), right = weights.reduce((a, b) => a + b, 0);
    while (left < right) {
        let mid = Math.floor((left + right) / 2);
        if (canShip(mid)) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }
    return left;
};
      

Problem Description

You are given an array weights where weights[i] is the weight of the i-th package, and an integer D representing the number of days within which all the packages must be shipped. Each day, you must load the packages onto a ship in the order given by the array. The ship has a maximum capacity (the same every day), and you cannot load more weight than this capacity in a single day. Packages must be shipped in order; you cannot skip or reorder them. Your goal is to find the minimum ship capacity required to ship all packages within D days.

  • Each package must be shipped in the order given (no reordering).
  • Each day, the total weight loaded must not exceed the ship's capacity.
  • Return the minimum possible ship capacity to ship all packages within D days.

Thought Process

At first, you might consider trying every possible way to split the packages into D groups, but this quickly becomes infeasible as the number of packages grows. Instead, notice that the key challenge is to determine the smallest possible ship capacity that allows us to ship all packages in order within D days.

If the ship's capacity is very large (e.g., the sum of all weights), we can ship all packages in one day. If the capacity is very small (e.g., the heaviest package), it might require many days. The problem is thus about finding the minimum ship capacity for which it is possible to ship all packages within D days. This is a classic "search for minimum feasible value" problem, which is well-suited to a binary search approach.

Solution Approach

  • Step 1: Define the Search Space
    • The minimum possible capacity is the weight of the heaviest package (since you can't split packages).
    • The maximum possible capacity is the sum of all package weights (ship everything in one day).
  • Step 2: Binary Search for the Minimum Capacity
    • Use binary search between the minimum and maximum capacities.
    • For each candidate capacity (the middle of the current range), check if it's possible to ship all packages within D days using that capacity.
    • If it is possible, try a smaller capacity (move left); otherwise, try a larger capacity (move right).
  • Step 3: Feasibility Check Function
    • Simulate the process: iterate through the packages, loading them onto the ship until the day's total would exceed the candidate capacity, then start a new day.
    • Count the number of days needed. If it's within D, the capacity is feasible.
  • Step 4: Return the Final Answer
    • When the binary search completes, the left boundary will be the minimum feasible capacity.

This approach is efficient because it avoids checking every possible grouping, and instead leverages the monotonic nature of the problem (i.e., increasing the capacity never makes the task harder).

Example Walkthrough

Suppose weights = [1,2,3,4,5,6,7,8,9,10] and D = 5.

  1. Set the search space:
    • Minimum capacity = 10 (heaviest package)
    • Maximum capacity = 55 (sum of all packages)
  2. First binary search step:
    • Mid = (10 + 55) // 2 = 32
    • Check if capacity 32 can ship in 5 days:
    • Day 1: 1+2+3+4+5+6+7 = 28 (next package 8 would exceed 32), so start new day
    • Day 2: 8+9 = 17 (next package 10 would exceed 32), so start new day
    • Day 3: 10
    • Used 3 days (less than 5), so try smaller capacity
  3. Next binary search step:
    • Mid = (10 + 32) // 2 = 21
    • Simulate: Day 1: 1+2+3+4+5+6 = 21 (next is 7), start new day
    • Day 2: 7+8 = 15 (next is 9), start new day
    • Day 3: 9+10 = 19
    • Used 3 days, try even smaller capacity
  4. Continue narrowing down:
    • Eventually, binary search will find that 15 is the minimum capacity to ship all packages within 5 days.

This step-by-step halving of the search interval quickly homes in on the answer.

Time and Space Complexity

  • Brute-force approach:
    • Trying every way to partition the array into D groups is exponential and infeasible for large inputs.
  • Optimized (Binary Search) approach:
    • The binary search runs in O(log(S)) time, where S is the sum of all weights minus the max weight.
    • For each binary search guess, we scan the weights array once to simulate the shipping, which takes O(N) time.
    • Therefore, overall time complexity is O(N log S).
    • Space complexity is O(1), since we only use a few variables for counting and boundaries.

Summary

The problem is about finding the minimum ship capacity to deliver packages within a given number of days, shipping packages in order and without exceeding the daily capacity. By recognizing the problem's monotonic nature, we can use binary search to efficiently find the answer, checking each candidate capacity with a simple simulation. This approach is both efficient and elegant, avoiding brute-force enumeration and leveraging a classic algorithmic technique.