LeetCode332 - Reconstruct Itinerary(重新安排行程 圖轉樹 後序遍歷)
阿新 • • 發佈:2019-01-07
LeetCode332 - Reconstruct Itinerary(重新安排行程 圖轉樹 後序遍歷)
題目連結
題目
解析
-
由於必須要按照字典序最小的來訪問某個結點的孩子,所以在查詢節點的孩子的
map
中使用一個優先佇列存放,每次取出來的是字典序最小的; -
然後按照類似後序遍歷的順序遍歷這個圖(先訪問自己孩子,然後訪問自己),然後在反轉過來,這樣可以得到正確的答案;
-
也可以理解為
dfs
的時候,是先訪問自己的孩子,然後訪問自己,最後將訪問的順序翻轉過來即可,需要注意的時候一定要使用後序的方式,不然會在選擇的時候出錯(或者說不能正確訪問所有的結點);
class Solution {
private HashMap<String, PriorityQueue<String>> map;
private List<String>res;
public List<String> findItinerary(String[][] tickets) {
res = new LinkedList<>();
map = new HashMap<>();
for (String[ ] s : tickets) {
if (map.get(s[0]) == null) {
PriorityQueue<String>pq = new PriorityQueue<>();
pq.add(s[1]);
map.put(s[0], pq);
}else {
map.get(s[0]).add(s[1]);
}
}
visit("JFK" );
return res;
}
public void visit(String cur) {
while(map.containsKey(cur) && !map.get(cur).isEmpty())
visit(map.get(cur).poll()); // 訪問孩子(最小的孩子)並刪除這條邊
res.add(0, cur); // 在頭部新增 (雙向佇列)
}
}
非遞迴寫法:
class Solution {
private HashMap<String, PriorityQueue<String>> map;
private List<String>res;
public List<String> findItinerary(String[][] tickets) {
res = new LinkedList<>();
map = new HashMap<>();
for (String[] s : tickets) {
if (map.get(s[0]) == null) {
PriorityQueue<String>pq = new PriorityQueue<>();
pq.add(s[1]);
map.put(s[0], pq);
}else {
map.get(s[0]).add(s[1]);
}
}
Stack<String>stack = new Stack<>();
stack.push("JFK");
while(!stack.isEmpty()){
while(map.containsKey(stack.peek()) && !map.get(stack.peek()).isEmpty())
stack.push(map.get(stack.peek()).poll());
res.add(0, stack.pop());
}
return res;
}
}
C++
:
class Solution {
public:
vector<string> findItinerary(vector<pair<string, string>> tickets) {
for(const auto & pair : tickets)
map[pair.first].insert(pair.second);
visit("JFK");
return vector<string>(res.rbegin(), res.rend());
}
private:
unordered_map<string, multiset<string>>map;
vector<string>res;
void visit(string cur){
while(map[cur].size()){
string next = *map[cur].begin();
map[cur].erase(map[cur].begin());
visit(next);
}
res.push_back(cur);
}
};