Problem Walkthrough

Boats to Save People LeetCode 881

Sort by weight, then use two pointers to greedily pair the heaviest remaining person with the lightest; if they fit together both board, otherwise the heaviest goes alone.

7 min read|

Boats to Save People

LeetCode 881

Problem Overview

LeetCode 881 — Boats to Save People — gives you an array people where people[i] is the weight of the i-th person, and an integer limit representing the maximum weight a single boat can carry. At most 2 people can share a boat. Your goal is to return the minimum number of boats required to carry every person.

The constraint that each boat holds at most 2 people is critical. This means every boat carries either one person or two people, never more. The weight limit applies to the total weight of everyone in that boat. If two people board together, the sum of their weights must not exceed limit.

The minimum number of boats problem is a classic greedy exercise. The key insight is that to minimize boats, you want to maximize the number of boats that carry two people rather than one. Doing this optimally requires a careful pairing strategy.

  • Input: array people[] of weights, integer limit (max weight per boat)
  • Constraint: at most 2 people per boat
  • Condition: sum of weights in a boat must not exceed limit
  • Goal: return the minimum number of boats needed to rescue everyone
  • Every person must be rescued — no one is left behind

Sort + Two Pointers

The algorithm starts by sorting the people array in non-decreasing order. With the array sorted, we place one pointer at the left end (the lightest person) and one at the right end (the heaviest person). On each iteration we check whether the heaviest and lightest remaining people can share a boat.

If people[left] + people[right] <= limit, both can share a boat. Both board together, so we advance left forward and right backward. If the sum exceeds limit, the heaviest person must go alone since no one heavier than the lightest can possibly fit with them. We advance only right backward and count one boat.

We continue this process while left <= right. Each iteration consumes at least one person (right always decrements), guaranteeing termination. The boats counter increments by 1 on every iteration regardless of whether one or two people board.

💡

The Greedy Choice

Always try to pair the heaviest remaining person with the lightest. If even the lightest person cannot fit with the heaviest, then nobody else can — the heaviest must go alone. This greedy rule is optimal because pairing heavy with light maximizes the chance of fitting two people per boat.

Algorithm

The full algorithm is concise: sort people, then run a two-pointer loop. Left starts at index 0, right starts at n-1, and boats starts at 0. Each iteration of the while loop accounts for at least one boat.

When the two-pointer condition people[left] + people[right] <= limit is met, both pointers move inward. Otherwise only right moves inward. In both cases we increment boats. The loop terminates when left > right, meaning all people have been assigned to a boat.

The time complexity is O(n log n) dominated by the sort. The two-pointer pass is O(n) since left and right together traverse the array exactly once. Space complexity is O(1) beyond the sort, as no additional data structures are needed.

  1. 1Sort people in non-decreasing order
  2. 2Initialize left = 0, right = n - 1, boats = 0
  3. 3While left <= right:
  4. 4 If people[left] + people[right] <= limit: left++ (both board together)
  5. 5 right-- (heaviest always boards — alone or with lightest)
  6. 6 boats++
  7. 7Return boats

Why Greedy Is Optimal

The greedy pairing strategy — heaviest with lightest — is provably optimal via an exchange argument. Suppose an optimal solution pairs the heaviest person H with some person M (not the lightest, L). We can swap M and L in the solution: H goes with L, and M either goes alone or with whoever L was previously paired with.

Because L is lighter than M, H + L <= H + M <= limit, so the swap is valid. The total number of boats does not increase — if H + M needed one boat, then H + L also fits in one boat and M may save a spot that reduces another boat. This exchange shows that pairing heavy with light never requires more boats.

An intuitive way to see it: the heaviest person is the hardest to pair. Giving them the best possible partner (the lightest person) maximizes the chance of a successful pairing. If even the lightest person cannot fit with the heaviest, then no pairing is possible for the heaviest and they must go alone — exactly what the algorithm does.

ℹ️

The Exchange Argument

If a valid pairing exists in any optimal solution, rearranging it to pair the heaviest with the lightest never uses more boats. The greedy heavy-light pairing is therefore always at least as good as any other pairing strategy, making it globally optimal.

Walk-Through Example

Consider people = [3, 2, 2, 1], limit = 3. After sorting the array becomes [1, 2, 2, 3]. We set left = 0, right = 3, boats = 0 and begin the two-pointer loop.

Iteration 1: people[left]=1, people[right]=3. Sum = 4 > 3, so 3 goes alone. right-- → right=2, boats=1. Iteration 2: people[left]=1, people[right]=2. Sum = 3 <= 3, so both board. left++ → left=1, right-- → right=1, boats=2.

Iteration 3: left=1 == right=1. people[left]=2 alone (only one person remains). right-- → right=0, boats=3. Now left > right, loop ends. Total boats = 3.

  1. 1Input: people=[3,2,2,1], limit=3
  2. 2After sort: [1, 2, 2, 3]
  3. 3left=0, right=3: 1+3=4 > 3 → 3 alone → boats=1, right=2
  4. 4left=0, right=2: 1+2=3 <= 3 → both board → boats=2, left=1, right=1
  5. 5left=1, right=1: only person 2 remains → 2 alone → boats=3, right=0
  6. 6left(1) > right(0): loop ends
  7. 7Answer: 3 boats

Code Walkthrough Python and Java

In Python: sort people, set left = 0 and right = len(people) - 1, boats = 0. Enter a while loop while left <= right. Inside the loop, check if people[left] + people[right] <= limit — if so, increment left. Always decrement right and increment boats. Return boats. Time O(n log n), space O(1).

In Java: Arrays.sort(people), then the same two-pointer pattern. Use int left = 0, right = people.length - 1, boats = 0. The while (left <= right) loop checks people[left] + people[right] <= limit to potentially advance left. Always advance right-- and boats++. Return boats.

A key implementation note: right always decrements on every iteration. This is because the heaviest person (at right) always boards a boat — either alone or with the lightest. We never skip the heaviest without placing them on a boat. left only increments when a valid pairing is found.

⚠️

At Most 2 Per Boat

Each boat carries at most 2 people — not unlimited. Do not attempt to fit 3 or more people per boat. Each iteration of the while loop represents exactly one boat: it carries either just people[right] (alone) or both people[left] and people[right] together. The right pointer always decrements; left only decrements when a valid pair is found.

Ready to master algorithm patterns?

YeetCode flashcards help you build pattern recognition through active recall and spaced repetition.

Start practicing now