题目描述
思路解析动画文字版
记住这句,下面每一帧都在套它。
最多 2 次中转 = 路径最多 3 条边。先把起点 0 记成 0,其余记 ∞;准备做 3 轮松弛,每轮让路径“多走一条边”。
第 1 轮 · 边 0→1:用上一轮的 dist[0]=0 加票价 100 = 100,比原来的 ∞ 便宜 → 更新 dist[1]=100。
第 1 轮 · 边 0→2:用上一轮的 dist[0]=0 加票价 500 = 500,比原来的 ∞ 便宜 → 更新 dist[2]=500。
第 1 轮 · 边 1→2:上一轮还没到过 1(dist=∞),这条边暂时用不上,跳过。
第 1 轮 · 边 1→3:上一轮还没到过 1(dist=∞),这条边暂时用不上,跳过。
第 1 轮 · 边 2→4:上一轮还没到过 2(dist=∞),这条边暂时用不上,跳过。
第 1 轮 · 边 3→4:上一轮还没到过 3(dist=∞),这条边暂时用不上,跳过。
第 1 轮松弛完毕:此时的 dist 是“最多走 1 条边”能拿到的最便宜价。终点 4 这轮还到不了。
第 2 轮 · 边 0→1:dist[0]=0 加票价 100 = 100,不比现有的 100 便宜 → 不更新。
第 2 轮 · 边 0→2:dist[0]=0 加票价 500 = 500,不比现有的 500 便宜 → 不更新。
第 2 轮 · 边 1→2:用上一轮的 dist[1]=100 加票价 100 = 200,比原来的 500 便宜 → 更新 dist[2]=200。
第 2 轮 · 边 1→3:用上一轮的 dist[1]=100 加票价 100 = 200,比原来的 ∞ 便宜 → 更新 dist[3]=200。
第 2 轮 · 边 2→4:用上一轮的 dist[2]=500 加票价 200 = 700,比原来的 ∞ 便宜 → 更新 dist[4]=700。
第 2 轮 · 边 3→4:上一轮还没到过 3(dist=∞),这条边暂时用不上,跳过。
第 2 轮松弛完毕:此时的 dist 是“最多走 2 条边”能拿到的最便宜价。到终点 4 暂为 700。
第 3 轮 · 边 0→1:dist[0]=0 加票价 100 = 100,不比现有的 100 便宜 → 不更新。
第 3 轮 · 边 0→2:dist[0]=0 加票价 500 = 500,不比现有的 200 便宜 → 不更新。
第 3 轮 · 边 1→2:dist[1]=100 加票价 100 = 200,不比现有的 200 便宜 → 不更新。
第 3 轮 · 边 1→3:dist[1]=100 加票价 100 = 200,不比现有的 200 便宜 → 不更新。
第 3 轮 · 边 2→4:用上一轮的 dist[2]=200 加票价 200 = 400,比原来的 700 便宜 → 更新 dist[4]=400。
第 3 轮 · 边 3→4:用上一轮的 dist[3]=200 加票价 100 = 300,比原来的 400 便宜 → 更新 dist[4]=300。
第 3 轮松弛完毕:此时的 dist 是“最多走 3 条边”能拿到的最便宜价。到终点 4 暂为 300。
3 轮全部做完,每轮只让路径多一条边,自然卡住了“最多 2 次中转”。终点 4 的 dist = 300,就是答案。
边界先想清。
两个高频追问。
参考代码
def findCheapestPrice(n, flights, src, dst, k): INF = float("inf") dist = [INF] * n dist[src] = 0 for _ in range(k + 1): # K+1 轮 snap = dist[:] # 上一轮快照 for u, v, w in flights: if snap[u] + w < dist[v]: dist[v] = snap[u] + w return -1 if dist[dst] == INF else dist[dst]复杂度
- 时间:O(K · E),K+1 轮,每轮松弛全部 E 条边
- 空间:O(n),dist 数组 + 一份快照
易错点
面试追问把动画讲成自己的话
追问为什么每轮要用上一轮的快照,而不是原地更新?
追问能不能用 Dijkstra 做这题?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。再去主线里挑下一道练手。
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题