题目描述
思路解析动画文字版
写一个 check(cap):按顺序贪心装船,装不下就开新一天;天数不超过 days 就可行。
1. 题面 · 顺序装船:5 个包裹按给定顺序排队,总重 9,最重一件是 3;要求 3 天内全部送完,求每天船的最小运载能力。
2. 不二分包裹,二分「容量」:把每个格子看成一个候选容量:最小取 max(weights)=3,最大取 sum=9。答案一定在这 7 个值里,对容量做二分。
3. 单调性 = 二分的前提:容量从 3 加到 9,需要的天数从 4 一路降到 1,单调不增;于是「是否可行」沿区间单调,正好能二分。
4. 第一轮 · 取中点 mid=6:区间 [3,9] 取中点容量 6(绿色格)。下一步用 check(6) 模拟装船,看 3 天够不够。
5. check(6) · 第 1 天装船:容量 6:从左到右装,第 1 天装下 2、3、1 共 6,正好装满(绿色三件)。下一件再加就超容量了。
6. check(6) · 开第 2 天:第 1 天的 3 件灰掉(已送),剩下 1、2 放第 2 天,载重 3。一共只用了 2 天。
7. mid=6 可行 → 收右界:2 天小于等于限制 3,容量 6 可行。但要找最小值,所以保留 6 当候选并向左缩:r 移到 6,灰掉 7、8、9。区间变为 [3,6]。
8. 第二轮 · 取中点 mid=4:新区间 [3,6] 取中点容量 4(绿色格)。再跑一次 check(4)。
9. check(4) · 模拟装船需 3 天:容量 4 时贪心分成三段:第 1 天只装 2,第 2 天装 3+1=4,第 3 天装 1+2=3,共 3 天。
10. mid=4 可行 → 再收右界:3 天正好等于限制 3,容量 4 仍可行,候选更新成 4。r 移到 4,灰掉 5、6。区间收成 [3,4]。
11. 第三轮 · 取中点 mid=3:区间 [3,4] 取中点容量 3(绿色格)。这是最小可能容量,再验一次 check(3)。
12. check(3) · 需要 4 天:容量只有 3 时装得很散:2 单独一天,3 单独一天,1+1 一天,最后 2 一天,共 4 天。
13. mid=3 不可行 → 收左界:4 天超过限制 3,容量 3 不可行,连同它一起灰掉。l 跳到 mid+1=4,此时 l 与 r 都等于 4。
14. l 等于 r · 区间收敛:左右界都收敛到 4,循环结束。返回 l=4,这正是第一个让 check 可行的容量。
15. 雷区 · 不能打乱顺序:两个常见坑:左界写成 1 会让小于最重包裹的容量当天装不下;check 里若重排包裹就违反「按传送带顺序」的题意。
“最小可行值 / 最大可行值”这类题,先找单调性,再写 check。
参考代码
class Solution: def shipWithinDays(self, weights, days): def need_days(cap): used = 1 cur = 0 for w in weights: if cur + w > cap: used += 1 cur = 0 cur += w return used l, r = max(weights), sum(weights) while l < r: mid = (l + r) // 2 if need_days(mid) <= days: r = mid else: l = mid + 1 return l复杂度
- 时间复杂度:O(n log S),S=sum(weights),每次 check 扫一遍
- 空间复杂度:O(1),只用几个变量
可套用的代码模板
这段代码可以按 LeetCode Python 模板直接提交;变量名和动画里的核心状态保持一致。
Python
class Solution: def answer(self, nums): def check(x): return True l, r = min_possible, max_possible while l < r: mid = (l + r) // 2 if check(mid): r = mid else: l = mid + 1 return l易错点
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。再去主线里挑下一道练手。
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题