题目描述
思路解析动画文字版
下面 16 步动画会按主解代码推进,而不是泛泛讲题型。
1. 题面 · 救生艇:有 4 个人,体重 [3,2,2,1],每艘船最多坐 2 人且两人体重之和不超过 3,求载完所有人需要的最少船数。
2. 先排序 · 让最轻最重对齐两端:先把体重从小到大排序得到 [1,2,2,3],这样最轻的人在最左、最重的人在最右,方便用双指针从两端往中间凑。
3. 贪心思路 · 最重的人必须上船:每轮都先安置当前最重的人(右指针 r):如果他能和当前最轻的人(左指针 l)合坐就一起,否则他只能单独一艘船。
4. 初始化双指针:左指针 l 指向下标 0(体重 1),右指针 r 指向下标 3(体重 3),船数 ans 从 0 开始。
5. 第 1 轮 · 取两端求和:看 l 和 r 两端:people[0]=1 加 people[3]=3 等于 4,先算出这个和再和 limit 比较,看最轻和最重能否合坐一船。
6. 第 1 轮 · 4 大于 3 配不上:两端和 4 大于 limit 3,最轻和最重凑不到一船。于是 if 分支不进,l 不动;最重的人(绿色)只能自己单独坐一艘船。
7. 第 1 轮 · 最重的人单独上船:无论配没配上,最重的人这轮都已安置:r 左移到 2,ans 加到 1。下标 3 的人(灰色)已送走,不再参与。
8. 第 2 轮 · 取两端求和:l 仍在 0(体重 1),r 现在是 2(体重 2)。两端和 people[0]+people[2]=1+2=3,再和 limit 比较。
9. 第 2 轮 · 3 不超过 3 可合坐:两端和 3 不超过 limit 3,最轻(下标 0)和当前最重(下标 2)可以合坐一船(两个绿色一起上)。if 分支成立,l 这轮要右移。
10. 第 2 轮 · 两人一起上船:合坐成功:l 右移到 1、r 左移到 1,两人都送走(下标 0 和 2 灰掉),ans 加到 2。现在 l 和 r 都指向下标 1。
11. 第 3 轮 · l 等于 r 仍要处理:l 等于 r 时循环条件 l 小于等于 r 仍成立,剩下的这 1 个人还要安置。两端和按公式算是 people[1]+people[1]=4,本质就是这一个人自己。
12. 第 3 轮 · 最后一人单独上船:和 4 大于 limit 3,不满足合坐条件,这个人单独一船。r 左移到 0、ans 加到 3,所有人都已安置(全部灰掉)。
13. 循环结束 · 指针交错:左指针 l=1 已越过右指针 r=0,循环条件 l 小于等于 r 不再成立,主循环退出,每个人都恰好被安排过一次。
14. 返回答案 · ans=3:返回 ans=3:分别是「3 单独一船」「1+2 合坐一船」「2 单独一船」,三艘船正好载完所有人。
15. 为何贪心正确 · 不变量:每轮让最重的人尝试配最轻的人:若最轻都配不上,其他更重的人更配不上,他注定单独一船;若配上了也不会更差。所以这个贪心一定是最少船数。
16. 雷区 · 两个易错点:两个常见坑:一是要先安置最重的人而不是最轻的人,因为最重的人选择空间最小;二是配对成功时两个人都上了船,l 和 r 都要移动,不能只动一个。
记住这题的代码骨架:题意约束先落到状态变量,再用循环或递归维护它。
参考代码
class Solution: def numRescueBoats(self, people, limit): people.sort() l = 0 r = len(people) - 1 ans = 0 while l <= r: if people[l] + people[r] <= limit: l += 1 r -= 1 ans += 1 return ans复杂度
- 时间复杂度:O(n log n),排序
- 空间复杂度:O(1),只用双指针
易错点
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
合并三元组以形成目标三元组
LeetCode 1899 · 中等 · 沿着 贪心套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题