π Try This Problem First!
Before reading the solution, attempt it yourself on LeetCode β you'll retain the concept far better.
π Problem Link: https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/
1. Understanding the Problem
You have a conveyor belt carrying N packages, each with a given weight. A ship must transport all of them within at most D days. Every day, you load packages in order (no rearranging allowed), and you cannot exceed the ship's weight capacity in a single day.
Goal: Find the minimum weight capacity of the ship such that all packages are delivered within D days.
Constraints:
- 1 β€ days β€ weights.length β€ 5 Γ 10β΄
- 1 β€ weights[i] β€ 500
2. Two Key Observations (Before Writing a Single Line of Code)
Before jumping to code, anchor yourself with these two facts:
Minimum possible capacity: The ship must at least be able to carry the single heaviest package. If it can't, that package can never be shipped. So:
low = max(weights)
Maximum possible capacity: If the ship can carry everything at once, it finishes in 1 day β always valid. So:
high = sum(weights)
Our answer lies somewhere in the range [max(weights), sum(weights)]. This is the classic setup for Binary Search on the Answer.
3. Intuition β Why Binary Search?
Ask yourself: what happens as ship capacity increases?
The number of days needed decreases or stays the same. This is a monotonic relationship β and monotonicity is the green flag for Binary Search.
Instead of checking every capacity from 1 to sum(weights) (which is huge), we binary search over the capacity space and for each candidate capacity mid, we ask:
"Can all packages be shipped in β€ D days with this capacity?"
This feasibility check runs in O(N) using a greedy simulation, making the whole approach O(N log(sum(weights))).
4. The Feasibility Check β Greedy Loading
Given a capacity mid, simulate loading the ship greedily:
- Keep adding packages to today's load.
- The moment adding the next package would exceed
mid, start a new day and reset the current load to that package. - Count total days used.
- If
days used β€ D, capacitymidis feasible.
5. Binary Search Strategy
- If
canShip(mid)is true βmidmight be the answer, but try smaller. Setans = mid,high = mid - 1. - If
canShip(mid)is false β capacity is too small, increase it. Setlow = mid + 1.
6. Dry Run β Example 1
Input: weights = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], days = 5
- low = 10 (max weight), high = 55 (sum of weights)
| Iteration | low | high | mid | Days Needed | Feasible? | ans |
| 1 | 10 | 55 | 32 | 2 | β Yes | 32 |
| 2 | 10 | 31 | 20 | 3 | β Yes | 20 |
| 3 | 10 | 19 | 14 | 6 | β No | 20 |
| 4 | 15 | 19 | 17 | 5 | β Yes | 17 |
| 5 | 15 | 16 | 15 | 5 | β Yes | 15 |
| 6 | 15 | 14 | β | loop ends | β | 15 |
Output: 15 β
7. The Code Implementation
8. Code Walkthrough β Step by Step
Step 1 β Setting bounds: We iterate through the weights array once to compute low = max(weights) and high = sum(weights). These are our binary search boundaries.
Step 2 β Binary Search loop: We pick mid = low + (high - low) / 2 (safe overflow-free midpoint). We check if capacity mid can ship all packages in β€ D days.
Step 3 β Feasibility helper (canShip): We simulate a greedy day-by-day loading. We start with daysNeeded = 1 and currentLoad = 0. For each package, if it fits in today's load, we add it. If not, we start a new day. The key line is:
Step 4 β Narrowing the search: If feasible β ans = mid, high = mid - 1 (try smaller). If not feasible β low = mid + 1 (try larger).
9. Common Mistakes to Avoid
Mistake 1 β Wrong lower bound: Using low = 1 instead of low = max(weights) works but is far slower since you binary search over a much larger range unnecessarily.
Mistake 2 β Wrong condition in canShip: The return should be daysNeeded <= days (not < days). If days needed equals D, it's still valid.
Mistake 3 β Off-by-one in greedy loading: When a package doesn't fit, you start a new day with that package as the first item: currentLoad = arr[i]. Do NOT set currentLoad = 0 β that package must still be accounted for.
Mistake 4 β Integer overflow in midpoint: Always use mid = low + (high - low) / 2 instead of (low + high) / 2 to avoid overflow when low and high are large.
10. Complexity Analysis
Time Complexity: O(N Γ log(sum(weights)))
- Binary search runs over the range [max(weights), sum(weights)], which has at most sum(weights) β 500 Γ 50000 = 25,000,000 values β about logβ(25,000,000) β 25 iterations.
- Each iteration calls
canShipwhich is O(N). - Total: O(N log S) where S = sum(weights).
Space Complexity: O(1)
- No extra data structures. Only a handful of integer variables are used.
11. Similar Problems (Same Pattern β Binary Search on Answer)
Once you understand this pattern, the following problems become very similar:
- LeetCode 410 β Split Array Largest Sum
- LeetCode 875 β Koko Eating Bananas [ Blog is also avaliable on this - Read Now ]
- LeetCode 1283 β Find the Smallest Divisor Given a Threshold
- LeetCode 2064 β Minimized Maximum of Products Distributed to Any Store
All of these follow the same template: define a feasibility check, identify a monotonic answer space, and binary search over it.
12. Key Takeaways
β When you see "find the minimum/maximum value such that a condition holds" β think Binary Search on the Answer.
β The lower bound of the search space is the most constrained valid value (max weight here).
β The upper bound is the least constrained valid value (total weight here).
β The feasibility check must be O(N) or better to keep the overall complexity efficient.
β Greedy loading (pack as much as possible each day) is optimal here since packages must go in order.
Happy Coding! If this helped you, share it with a friend who's grinding LeetCode. π




