|
| 1 | +--- |
| 2 | +title: 881.救生艇 |
| 3 | +date: 2024-06-10 21:00:04 |
| 4 | +tags: [题解, LeetCode, 中等, 贪心, 数组, 双指针, 排序] |
| 5 | +--- |
| 6 | + |
| 7 | +# 【LetMeFly】881.救生艇:排序+双指针(大人掌船,能捎就捎) |
| 8 | + |
| 9 | +力扣题目链接:[https://leetcode.cn/problems/boats-to-save-people/](https://leetcode.cn/problems/boats-to-save-people/) |
| 10 | + |
| 11 | +<p>给定数组<meta charset="UTF-8" /> <code>people</code> 。<code>people[i]</code>表示第 <code>i</code><sup> </sup>个人的体重 ,<strong>船的数量不限</strong>,每艘船可以承载的最大重量为 <code>limit</code>。</p> |
| 12 | + |
| 13 | +<p>每艘船最多可同时载两人,但条件是这些人的重量之和最多为 <code>limit</code>。</p> |
| 14 | + |
| 15 | +<p>返回 <em>承载所有人所需的最小船数</em> 。</p> |
| 16 | + |
| 17 | +<p> </p> |
| 18 | + |
| 19 | +<p><strong>示例 1:</strong></p> |
| 20 | + |
| 21 | +<pre> |
| 22 | +<strong>输入:</strong>people = [1,2], limit = 3 |
| 23 | +<strong>输出:</strong>1 |
| 24 | +<strong>解释:</strong>1 艘船载 (1, 2) |
| 25 | +</pre> |
| 26 | + |
| 27 | +<p><strong>示例 2:</strong></p> |
| 28 | + |
| 29 | +<pre> |
| 30 | +<strong>输入:</strong>people = [3,2,2,1], limit = 3 |
| 31 | +<strong>输出:</strong>3 |
| 32 | +<strong>解释:</strong>3 艘船分别载 (1, 2), (2) 和 (3) |
| 33 | +</pre> |
| 34 | + |
| 35 | +<p><strong>示例 3:</strong></p> |
| 36 | + |
| 37 | +<pre> |
| 38 | +<strong>输入:</strong>people = [3,5,3,4], limit = 5 |
| 39 | +<strong>输出:</strong>4 |
| 40 | +<strong>解释:</strong>4 艘船分别载 (3), (3), (4), (5)</pre> |
| 41 | + |
| 42 | +<p> </p> |
| 43 | + |
| 44 | +<p><strong>提示:</strong></p> |
| 45 | + |
| 46 | +<ul> |
| 47 | + <li><code>1 <= people.length <= 5 * 10<sup>4</sup></code></li> |
| 48 | + <li><code>1 <= people[i] <= limit <= 3 * 10<sup>4</sup></code></li> |
| 49 | +</ul> |
| 50 | + |
| 51 | + |
| 52 | + |
| 53 | +## 解题方法:排序+双指针 |
| 54 | + |
| 55 | +### 具体做法 |
| 56 | + |
| 57 | +首先对所有人按体重从低到高排序。 |
| 58 | + |
| 59 | +使用两个指针$l$和$r$分别指向数组的第一个和最后一个元素。 |
| 60 | + |
| 61 | +每次$r$指针向前移动一个元素(并且救生艇数量加一),另外的,若$r$指针移动前$people[l]+people[r]\leq lmit$,则$l$指针右移一个元素(相当于大人捎个小孩)。 |
| 62 | + |
| 63 | +### 为什么这么做 |
| 64 | + |
| 65 | +**为什么r指针每次都移动而l指针不一定移动?** |
| 66 | + |
| 67 | +反正每个人都得坐船走,可以理解为先分配大人(每次r左移),若此大人还能捎带一个小孩儿,则就把这个小孩儿带走(此时l右移)。 |
| 68 | + |
| 69 | +**大人不应该带上“尽可能重的小孩”吗?** |
| 70 | + |
| 71 | +第一反应是这样的。对于大人$people[r]$,是否应该带上满足$people[i]+people[r]\leq limit$的最大$i$而不是剩下所有小孩中最小的$l$呢? |
| 72 | + |
| 73 | +其实带谁都一样。反正都是一个人头。此时$r$能带上“更重的小孩$i$”,那么待会儿“更轻的大人”也一定能带上小孩$i$。带$l$写起来简单,所以带$l$不带$i$。 |
| 74 | + |
| 75 | +### 时空复杂度分析 |
| 76 | + |
| 77 | ++ 时间复杂度$O(n\log n)$,其中$n=len(people)$ |
| 78 | ++ 空间复杂度$O(\log n)$ |
| 79 | + |
| 80 | +时空复杂度的来源主要是排序。 |
| 81 | + |
| 82 | +### AC代码 |
| 83 | + |
| 84 | +#### C++ |
| 85 | + |
| 86 | +```cpp |
| 87 | +class Solution { |
| 88 | +public: |
| 89 | + int numRescueBoats(vector<int>& people, int limit) { |
| 90 | + sort(people.begin(), people.end()); |
| 91 | + int ans = 0; |
| 92 | + for (int l = 0, r = people.size() - 1; l <= r; ans++, r--) { |
| 93 | + // 不用特判l是否等于r,因为不影响结果(若l=r则说明就剩一个人了,带不带那个“虚空影子”都无所谓) |
| 94 | + if (people[l] + people[r] <= limit) { |
| 95 | + l++; |
| 96 | + } |
| 97 | + } |
| 98 | + return ans; |
| 99 | + } |
| 100 | +}; |
| 101 | +``` |
| 102 | +
|
| 103 | +#### Go |
| 104 | +
|
| 105 | +```go |
| 106 | +// package main |
| 107 | +
|
| 108 | +// import "sort" |
| 109 | +
|
| 110 | +func numRescueBoats(people []int, limit int) int { |
| 111 | + sort.Ints(people); |
| 112 | + ans := 0 |
| 113 | + for l, r := 0, len(people) - 1; l <= r; ans, r = ans + 1, r - 1 { |
| 114 | + if people[l] + people[r] <= limit { |
| 115 | + l++; |
| 116 | + } |
| 117 | + } |
| 118 | + return ans |
| 119 | +} |
| 120 | +``` |
| 121 | + |
| 122 | +#### Java |
| 123 | + |
| 124 | +```java |
| 125 | +// import java.util.Arrays; |
| 126 | + |
| 127 | +class Solution { |
| 128 | + public int numRescueBoats(int[] people, int limit) { |
| 129 | + Arrays.sort(people); |
| 130 | + int ans = 0; |
| 131 | + for (int l = 0, r = people.length - 1; l <= r; ans++, r--) { |
| 132 | + if (people[l] + people[r] <= limit) { |
| 133 | + l++; |
| 134 | + } |
| 135 | + } |
| 136 | + return ans; |
| 137 | + } |
| 138 | +} |
| 139 | +``` |
| 140 | + |
| 141 | +#### Python |
| 142 | + |
| 143 | +```python |
| 144 | +# from typing import List |
| 145 | + |
| 146 | +class Solution: |
| 147 | + def numRescueBoats(self, people: List[int], limit: int) -> int: |
| 148 | + people.sort() |
| 149 | + ans = 0 |
| 150 | + l, r = 0, len(people) - 1 |
| 151 | + while l <= r: |
| 152 | + if people[l] + people[r] <= limit: |
| 153 | + l += 1 |
| 154 | + r -= 1 |
| 155 | + ans += 1 |
| 156 | + return ans |
| 157 | +``` |
| 158 | + |
| 159 | +> 同步发文于CSDN和我的[个人博客](https://blog.letmefly.xyz/),原创不易,转载经作者同意后请附上[原文链接](https://blog.letmefly.xyz/2024/06/10/LeetCode%200881.%E6%95%91%E7%94%9F%E8%89%87/)哦~ |
| 160 | +> |
| 161 | +> Tisfy:[https://letmefly.blog.csdn.net/article/details/139582336](https://letmefly.blog.csdn.net/article/details/139582336) |
0 commit comments