Skip to content

Commit 6283aba

Browse files
committed
feat(algorithms, greedy): minimimum boats to rescue people
1 parent b969f83 commit 6283aba

19 files changed

+168
-1
lines changed

algorithms/greedy/boats/README.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# Boats to save people
2+
3+
A big ship with numerous passengers is sinking, and there is a need to evacuate these people with the minimum number of
4+
life-saving boats. Each boat can carry, at most, two persons however, the weight of the people cannot exceed the
5+
carrying weight limit of the boat.
6+
7+
We are given an array, people, where people[i] is the weight of the `ith` person, and an infinite number of boats, where
8+
each boat can carry a maximum weight, limit. Each boat carries, at most, two people at the same time. This is provided
9+
that the sum of the weight of these people is under or equal to the weight limit.
10+
11+
You need to return the minimum number of boats to carry all persons in the array.
12+
13+
## Constraints
14+
15+
- 1 <= `people.length` <= 5 * 10^3
16+
- 1 <= `people[i]` <= `limit` <= 3 * 10^3
17+
18+
## Examples
19+
20+
![Example 1](./images/examples/boats_to_save_people_example_1.png)
21+
![Example 2](./images/examples/boats_to_save_people_example_2.png)
22+
![Example 3](./images/examples/boats_to_save_people_example_3.png)
23+
![Example 4](./images/examples/boats_to_save_people_example_4.png)
24+
![Example 5](./images/examples/boats_to_save_people_example_5.png)
25+
26+
## Solution
27+
28+
1. [Naive Approach](#naive-approach)
29+
2. [Optimized Approach Using Greedy Pattern](#greedy-pattern)
30+
31+
### Naive Approach
32+
33+
The naive approach is to use a nested loop. For each person, we can check all the remaining people to see if they can
34+
form a pair that fits into a boat. If we find a pair, we’ll remove them from the array, increment the number of boats
35+
used, and move to the next person. If we can’t find a pair for a person, we put them in a boat alone and increment the
36+
number of boats used. We repeat this process until all people are rescued.
37+
38+
The time complexity of this approach is O(n^2), since we’ll use the nested loop to make pairs.
39+
40+
### Greedy Pattern
41+
42+
To solve the problem, we can use the greedy pattern and pair people with the lightest and heaviest people available, as
43+
long as their combined weight does not exceed the weight limit. If the combined weight exceeds the limit, we can only
44+
send one person on that boat. This approach ensures that we use the minimum number of boats to rescue the people.
45+
46+
The steps to implement the approach above are given below:
47+
48+
1. Sort the people array in ascending order so that the lightest person is at the start of the array, and the heaviest
49+
person is at the end.
50+
51+
2. Initialize two pointers, left and right. The left pointer points to the lightest person at the start of the array,
52+
and the right pointer points to the heaviest person at the end of the array. Next, a variable, boats, is initialized
53+
to 0, representing the number of boats used.
54+
55+
3. Iterate over the people array until the left pointer is greater than the right pointer. This means that all people
56+
have been rescued. Perform the following steps in each iteration of the loop
57+
- Check if both the lightest and heaviest persons can fit in one boat, i.e., people[left] + people[right] is less
58+
than or equal to limit. If they can fit, the left pointer is incremented and the right pointer is decremented.
59+
- If they cannot fit in one boat, the heaviest person is rescued alone, and the right pointer is decremented.
60+
- The boats variable is incremented by 1, representing the number of boats used.
61+
62+
4. Return the minimum number of boats required to rescue all the people.
63+
64+
![Solution 1](./images/solutions/boats_to_save_people_solution_1.png)
65+
![Solution 2](./images/solutions/boats_to_save_people_solution_2.png)
66+
![Solution 3](./images/solutions/boats_to_save_people_solution_3.png)
67+
![Solution 4](./images/solutions/boats_to_save_people_solution_4.png)
68+
![Solution 5](./images/solutions/boats_to_save_people_solution_5.png)
69+
![Solution 6](./images/solutions/boats_to_save_people_solution_6.png)
70+
![Solution 7](./images/solutions/boats_to_save_people_solution_7.png)
71+
![Solution 8](./images/solutions/boats_to_save_people_solution_8.png)
72+
![Solution 9](./images/solutions/boats_to_save_people_solution_9.png)
73+
![Solution 10](./images/solutions/boats_to_save_people_solution_10.png)
74+
75+
#### Solution Summary
76+
77+
- Sort the people array.
78+
- Initialize two pointers—left at the start and right at the end of the array.
79+
- Iterate over the people array while the left pointer is less than or equal to the right pointer.
80+
- Check if both the lightest and heaviest persons can fit in one boat. If so, increment the left pointer and decrement
81+
the right pointer.
82+
- Otherwise, rescue the heaviest person alone and decrement the right pointer.
83+
- Increment the boats after each rescue operation.
84+
85+
#### Time Complexity
86+
87+
The time complexity for the solution is O(n log n), since sorting the people array takes O(n log n) time.
88+
89+
#### Space Complexity
90+
91+
The sorting algorithm takes O(n) space to sort the people array. Therefore, the space complexity of the solution above
92+
is O(n).
93+
94+
## Topics
95+
96+
- Greedy
97+
- Two Pointers
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from typing import List
2+
3+
4+
def rescue_boats(people: List[int], limit: int) -> int:
5+
"""
6+
Finds the minimum number of rescue boats that can be used to save people from a sinking ship. Note that the assumption
7+
made here is that the number of boats is unlimited
8+
Args:
9+
people (list): list of weights of people
10+
limit (int): weight limit of each boat
11+
Returns:
12+
int: minimum number of rescue boats required
13+
"""
14+
# copy over the people list to avoid mutating the input list
15+
weights = people[:]
16+
# sort the list of weights
17+
weights.sort()
18+
19+
# using two pointers to move along the weights to be able to track pairs of people, the left pointer will be at 0
20+
# initially, i.e. at the lighter person and the right pointer will be at the end of the list, which will be the heavier
21+
# person
22+
left_pointer, right_pointer = 0, len(weights) - 1
23+
24+
# this keeps track of the total rescue boats that will be used
25+
boats = 0
26+
27+
while left_pointer <= right_pointer:
28+
lightest = weights[left_pointer]
29+
heaviest = weights[right_pointer]
30+
current_weight = lightest + heaviest
31+
# If the current weight is less than the limit of a single boat
32+
if current_weight <= limit:
33+
# move to the next heavier person and back down the heavier scale
34+
left_pointer += 1
35+
# the heavier person boards the boat and we move the right pointer
36+
right_pointer -= 1
37+
38+
# either way, we increment the number of boats
39+
boats += 1
40+
41+
return boats
91.2 KB
Loading
92.2 KB
Loading
92.6 KB
Loading
99.3 KB
Loading
94.8 KB
Loading
54.1 KB
Loading
63.7 KB
Loading
55 KB
Loading

0 commit comments

Comments
 (0)