Problem
You have a list of people's weights and a boat that can carry at most two people, subject to a total weight limit. Find the minimum number of boats needed so that every person gets a boat.
- Input:
people = [3, 2, 2, 1],limit = 3 - Output:
3 - Explanation: The pairs
(1, 2),(2),(3)use three boats โ the person weighing 3 cannot share with anyone
A counter-example clarifies the pairing logic: people = [1, 2], limit = 2 needs 2 boats (1+2 > 2), not 1.
Intuition
Since each boat holds at most two people, you want to pair the heaviest remaining person with the lightest remaining person. If they fit together, great โ you've used two seats on one boat. If not, the heaviest must go alone because they can't pair with anyone heavier. Sorting makes both extremes accessible at every step.
Solution โ Sort and Two Pointers
Sort people by weight, then use a left pointer at the lightest end and a right pointer at the heaviest end. Every iteration, the heaviest person takes a boat; the only question is whether the lightest remaining person can join them.
- Sort
peoplein ascending order - Initialize
left = 0,right = len(people) - 1, andboats = 0 - While
left <= right: check ifpeople[left] + people[right] <= limit - If yes, advance
left(the lightest pairs with the heaviest) - Always advance
rightand incrementboats(the heaviest always departs) - Return
boats
1def numRescueBoats(people: list[int], limit: int) -> int:
2 people.sort()
3 left, right = 0, len(people) - 1
4 boats = 0
5
6 while left <= right:
7 if people[left] + people[right] <= limit:
8 left += 1 # lightest can share a boat with the heaviest
9 right -= 1 # heaviest always takes a boat this round
10 boats += 1
11
12 return boatsTime: O(n log n) โ dominated by sorting; the two-pointer scan is O(n)
Space: O(1) โ only two index variables beyond the input array
Complexity Summary
| Approach | Time | Space | When to use |
|---|---|---|---|
| Sort + Two Pointers | O(n log n) | O(1) | Anytime you need minimum boats with at-most-2 occupancy |
Common Mistakes
- Incrementing
boatsonly when a pair forms โ every loop iteration uses exactly one boat; the only choice is whether the lightest person joins the heaviest, not whether a boat leaves - Using
left < rightas the loop condition โ whenleft == rightthere is exactly one person left and they still need a boat;left <= rightensures this last person is counted - Not sorting first โ the greedy works because you always compare the absolute extremes; without sorting you cannot guarantee you are testing the true lightest and heaviest remaining
- Trying to pair the heaviest with the second-heaviest โ if the heaviest cannot pair with the lightest possible partner, they cannot pair with anyone heavier, so they must go alone
- Adding a special case for when
people[right] > limitโ the problem guaranteespeople[i] <= limit, meaning every person can always fit in a boat alone; no special handling is needed
Related Problems
Two Sum II โ Input Array Is Sortedโ same left-and-right pointer pattern on a sorted arrayContainer With Most Waterโ two pointers moving inward to optimize an objective3Sumโ extending two pointers to a three-pointer pattern on sorted inputSquares of a Sorted Arrayโ two pointers merging from the outer ends inward