332. Reconstruct Itinerary
題目網址:https://leetcode.cn/problems/reconstruct-itinerary/
題意:給一航線列表
tickets
, 其中tickets[i] = [from_i, to_i]
表示飛機出發和降落的地點。請你對該行程進行重新規劃排序。所有這些機票都屬於一個從
JFK
出發的人, 所以該行程必須從JFK
開始。如果存在多種有效的行程, 請你按字典排序返回最小的行程組合。e.g. 行程
["JFK", "LGA"]
與["JFK", "LGB"]
相比就更小, 排序會更靠前假定所有機票至少存在一種合理的行程。所有的機票都必須使用, 且每張只能用一次
Solution:
首先考慮下面這張圖, 總共有兩條合法路徑:
JFK ➔ AAA ➔ JFK ➔ BBB ➔ JFK
JFK ➔ BBB ➔ JFK ➔ AAA ➔ JFK
- 由於要選擇字典順序最小的, 所以我們選擇第一條
- 要如何每次都先拜訪最小的鄰近 node, 並記錄重複的點
➔ 將adj[v]
宣告成 multiset, 這樣 insert 到adj[v]
的 node 就會自動由小到大排序, 且允許重複元素。因為有可能v1
重複拜訪v2
多次, 由於每張票都必須被使用, 故adj[v1]
要重複紀錄v2
考慮下面的特殊情形:
- 若先拜訪
AAA
, 就沒辦法回到JFK
了 ➔ 這樣就無法拜訪剩餘的邊- 也就是說, 當我們 Greedy 拜訪順序最小的 node 時, 很可能會踏入「死路」導致無法遍歷所有的邊
- 因此, 我們利用 post order 倒著遍歷。若當前 node 不能繼續往下走, 則把它加到
res
中, 最後再將res
反轉即可
想法:利用 Hierholzer 演算法 (DFS + post order)
- 從起點出發, 進行 DFS
- 當沿著邊
e
從某個v1
移動到另外一個頂點v2
時, 需要刪除e
(避免重複拜訪)- 如果沒有可移動的路徑, 則將所在節點加入到
res
中, 並返回- 反轉
res
下圖可以看到由
tickets
所建立的 tree, 對該 tree 取 post order 再反轉即為答案
class Solution { |
- time:$O(E \cdot log(E))$ ➔ 從 multiset 中移除一條邊需花 $O(log(E))$, 總共需移除
E
條 - space:$O(V + E)$ ➔
adj
本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Zako's Blog!
評論