Compile Ready
Module 7 · Advanced Greedy

Boats to Save People

MediumProblem 21 of 21 7 min read ~15 min to solve LeetCode
GreedySortingTwo PointersArrayPairing
Asked atAmazonGoogleMetaMicrosoftApple

Problem Statement

You are given an array people, where people[i] is the weight of one person, and an integer limit. Each boat can carry at most two people at the same time, as long as their combined weight is at most limit.

Return the minimum number of boats needed to carry everyone. Every person's weight is at most limit, so each person can always ride alone if necessary.

Input

An integer array people of weights and an integer limit.

Output

An integer: the minimum number of boats required to rescue everyone.

Constraints

  • 1 <= people.length <= 5 * 10^4
  • 1 <= people[i] <= limit <= 3 * 10^4
  • Each boat carries at most two people

Examples

Example 1

Input:
people = [1,2], limit = 3
Output: 1
Explanation: The two people fit together in one boat because 1 + 2 <= 3.

Example 2

Input:
people = [3,2,2,1], limit = 3
Output: 3
Explanation: One 3-weight person rides alone, and the remaining people can be rescued as **[1,2]** and **[2]**.

Example 3

Input:
people = [3,5,3,4], limit = 5
Output: 4
Explanation: No pair with the 5-weight or 4-weight people fits, and the two 3-weight people also exceed the limit together.

Learning Objectives

  • Use sorting to expose the lightest and heaviest remaining people.
  • Explain why the heaviest remaining person should be assigned a boat immediately.
  • Prove the safe pairing of the heaviest person with the lightest possible partner.
  • Implement a two-pointer greedy loop without off-by-one errors.

Intuition

Focus on the heaviest remaining person. They must leave on the next boat in some optimal solution, either alone or with one partner. If even the lightest remaining person cannot fit with them, no one can, so sending the heaviest alone is forced.

If the lightest can fit with the heaviest, pairing them is safe. The lightest is the easiest person to pair with anyone else, but using them with the heaviest does not block a better pairing for the heaviest because every other possible partner is heavier. This gives the classic sorted two-pointer greedy: try to pair the extremes, always consume the heaviest, and use one boat per step.

Common mistakes

  • ×Trying to pair the two lightest people first, which can strand heavy people unnecessarily.
  • ×Moving both pointers even when the lightest does not fit with the heaviest.
  • ×Forgetting that each boat can carry at most two people, not any number under the limit.
  • ×Returning the number of successful pairs instead of the total number of boats.

Algorithm Explanation

Greedy strategy

Sort the weights. Keep left at the lightest remaining person and right at the heaviest remaining person. Use one boat for the heaviest person every iteration. If the lightest and heaviest fit together, put them together and move both pointers; otherwise, the heaviest rides alone and only right moves.

Why it works

The heaviest remaining person must be placed in some boat. If they cannot fit with the lightest remaining person, they cannot fit with anyone, so a solo boat is forced. If they can fit with the lightest, pairing them is safe because the lightest is the least restrictive possible partner, and the heaviest could not get a better partner that saves more than one boat.

Proof of correctness

Consider an optimal solution for the remaining people and let H be the heaviest person. If H cannot fit with the lightest person L, then H cannot fit with any remaining person, so every optimal solution gives H a solo boat, matching the greedy choice. If H can fit with L, take any optimal solution. If H already rides with L, it matches greedy. Otherwise, suppose H rides with P or alone, and L rides with Q or alone. Put H with L. If H was alone, the old boat containing L can still carry its other passenger alone if needed. If H rode with P and L was alone, then P can ride alone in L's old boat. If H rode with P and L rode with Q, then P + Q <= H + P <= limit because H is the heaviest person and H + P was valid, so P can take L's old place. In every case the boat count does not increase, creating an optimal solution matching the greedy choice. Repeating the argument proves the algorithm is optimal.

Algorithm

  1. Sort people in nondecreasing order.
  2. Set left = 0, right = people.length - 1, and boats = 0.
  3. While left <= right, reserve one boat for people[right].
  4. If people[left] + people[right] <= limit, increment left to include the lightest person in that boat.
  5. Always decrement right because the heaviest person has been assigned.
  6. Increment boats and continue until everyone is assigned.

Solutions

Solution: Sorted two pointers

After sorting, each step decides the fate of the heaviest remaining person. Pair them with the lightest remaining person if possible; otherwise send the heaviest alone.

Step-by-step

  1. Sort the weights in ascending order.
  2. Place left at the smallest weight and right at the largest weight.
  3. If the two weights fit within limit, move left because the lightest person shares the boat.
  4. Move right every iteration because the heaviest person is always assigned.
  5. Count one boat for each iteration and return the count.
Time

O(n log n)

Space

O(log n)

Sorting dominates the runtime; the two-pointer scan is linear and Java's primitive array sort uses logarithmic stack space.

Java implementation

Loading…

Dry Run

Sample input

people = [3,2,2,1], limit = 3. After sorting, weights are [1,2,2,3].

stepleft index and weightright index and weightdecisionboats used
10 -> 13 -> 31 + 3 > 3, send 3 alone1
20 -> 12 -> 21 + 2 <= 3, pair them2
31 -> 21 -> 2only one 2 remains, send alone3

Each row assigns the heaviest remaining person. The algorithm uses three boats, which is optimal for this input.

Interview Tips

Explain why the algorithm reasons about the heaviest remaining person, not the lightest. The heaviest has the fewest pairing options, so their boat should be decided now. If a pair with the lightest fails, the solo decision is forced; if it succeeds, pairing them cannot reduce future options in a way that costs an extra boat.

Likely follow-ups

  • What changes if each boat could carry up to **k** people instead of two?
  • How would you solve it if the weights were already sorted?
  • How would you return the actual boat assignments?
  • What if there were different boat limits instead of one shared **limit**?

Similar Problems

Key Takeaways

  • The heaviest remaining person is the constrained item and should be assigned immediately.
  • If the lightest cannot pair with the heaviest, nobody can.
  • If the lightest can pair with the heaviest, that pairing is safe by exchange.
  • One two-pointer iteration always consumes the heaviest person and exactly one boat.
Reusable template: Sort, then repeatedly decide the most constrained remaining item by pairing it with the least costly compatible partner when possible.