The "Boats to Save People" problem asks you to determine the minimum number of boats required to rescue all people, given certain constraints. Each person has a specific weight, represented as an integer in the people
array. Each boat can carry at most two people at the same time, provided the sum of their weights does not exceed the boat's weight limit, given as limit
. Every person must be rescued, and each person can be assigned to only one boat (no reuse).
Your task is to return the minimum number of boats needed to save everyone.
limit
.The first instinct might be to try every possible combination of people to fit into boats, but this would be too slow for large inputs. Instead, we can look for ways to pair up people efficiently so that as many boats as possible carry two people, minimizing the total number of boats.
A key insight is that pairing the lightest person with the heaviest person (when possible) will often maximize boat utilization. If the heaviest person cannot be paired with the lightest, then the heaviest person must go alone. This leads to a two-pointer strategy, which is much faster than checking all possible pairs.
Here’s a step-by-step breakdown of the optimized algorithm:
people
array: This allows us to efficiently pair the lightest and heaviest people.
i
) starts at the beginning (lightest person).j
) starts at the end (heaviest person).i <= j
:
i
and j
is less than or equal to limit
, pair them together in one boat and move both pointers inward (i++
, j--
).j
must go alone, so just move j--
.This approach ensures we use the fewest boats possible by always trying to fit two people per boat when feasible.
Let’s consider the example: people = [3, 2, 2, 1]
, limit = 3
.
people
: [1, 2, 2, 3]
i = 0
(points to 1), j = 3
(points to 3), boats = 0
.j
to 2. Boats = 1.i
to 1, j
to 1. Boats = 2.i == j
). Boats = 3.n
.
The "Boats to Save People" problem is elegantly solved by sorting the people by weight and using a two-pointer approach to pair the lightest and heaviest people wherever possible. This strategy ensures that we use the minimum number of boats by maximizing boat utilization, and it runs efficiently even for large input sizes.
class Solution:
def numRescueBoats(self, people, limit):
people.sort()
i, j = 0, len(people) - 1
boats = 0
while i <= j:
if people[i] + people[j] <= limit:
i += 1
j -= 1
boats += 1
return boats
class Solution {
public:
int numRescueBoats(vector<int>& people, int limit) {
sort(people.begin(), people.end());
int i = 0, j = people.size() - 1, boats = 0;
while (i <= j) {
if (people[i] + people[j] <= limit) {
i++;
}
j--;
boats++;
}
return boats;
}
};
class Solution {
public int numRescueBoats(int[] people, int limit) {
Arrays.sort(people);
int i = 0, j = people.length - 1, boats = 0;
while (i <= j) {
if (people[i] + people[j] <= limit) {
i++;
}
j--;
boats++;
}
return boats;
}
}
var numRescueBoats = function(people, limit) {
people.sort((a, b) => a - b);
let i = 0, j = people.length - 1, boats = 0;
while (i <= j) {
if (people[i] + people[j] <= limit) {
i++;
}
j--;
boats++;
}
return boats;
};