LeetCode332. 重新安排行程
題目
給定一個機票的字串二維陣列 [from, to],子陣列中的兩個成員分別表示飛機出發和降落的機場地點,對該行程進行重新規劃排序。所有這些機票都屬於一個從JFK(肯尼迪國際機場)出發的先生,所以該行程必須從 JFK 出發。
說明:
如果存在多種有效的行程,你可以按字元自然排序返回最小的行程組合。例如,行程 ["JFK", "LGA"] 與 ["JFK", "LGB"] 相比就更小,排序更靠前
所有的機場都用三個大寫字母表示(機場程式碼)。
假定所有機票至少存在一種合理的行程。
示例 1:
輸入: [[“MUC”, “LHR”], [“JFK”, “MUC”], [“SFO”, “SJC”], [“LHR”, “SFO”]]
輸出: [“JFK”, “MUC”, “LHR”, “SFO”, “SJC”]
示例 2:
輸入: [[“JFK”,“SFO”],[“JFK”,“ATL”],[“SFO”,“ATL”],[“ATL”,“JFK”],[“ATL”,“SFO”]]
輸出: [“JFK”,“ATL”,“JFK”,“SFO”,“ATL”,“SFO”]
解釋: 另一種有效的行程是 [“JFK”,“SFO”,“ATL”,“JFK”,“ATL”,“SFO”]。但是它自然排序更大更靠後。
分析
最近演算法課上講了圖,所以想著這周練習下有關圖的演算法題。
這個題一開始沒有看太懂,坐著飛機幾個地方繞來繞去,我真是搞不懂為什麼要拿這個東西做例題。。。。。
好啦大概題意就是說,我找到一條路徑,可以把這幾條路徑一次走完,而且,要按照機場的程式碼排序,也就是按照字串abc排序。
這個題有兩個地方要解決的,第一個就是要把所有路徑一次走完,第二個是走的過程我還要先走程式碼儘量小的。
也就是第一個問題深度優先遍歷,第二個排序。
那深度優先遍歷還好說,就一直去找下一節點,沒有了就返回,但是排序這個我就有點懵圈了,我要把所有結果都走出來再排麼,這時間怕是很長吧。。
然後看了網上解題報告,嗯,大家用的是優先佇列來解決的。
首先我們要把二維字串陣列儲存到一個map裡,代表一個 from—— [to1,to2 …] , 在儲存from對應的to地點的時候,我們把它儲存到優先佇列裡,自然排序小的在前面,這樣,我們在dfs的時候,就可以通過poll來取到最小的啦。
圖構建好了之後就是去dfs,按照題目要求從"JFK"開始,找下一個地點, 當發現某個from沒有在map裡或者某個from對應的優先佇列為空,這就代表它沒有了下一個節點,放到最後結果的list集合裡。
當from對應的佇列長度>0,那麼就依次去dfs佇列裡面的地點, 全部dfs完之後記得list.add上from,因為它終要回到這裡。
程式碼
class Solution {
static Map<String, PriorityQueue<String>> map = new HashMap<String, PriorityQueue<String>>();
static List<String> list = new ArrayList<String>();
public static List<String> findItinerary(String[][] tickets) {
map.clear();
list.clear();
for (String[] strings : tickets) {
if (map.containsKey(strings[0])){
map.get(strings[0]).add(strings[1]);
}else{
PriorityQueue<String> pqt = new PriorityQueue<String>();
pqt.add(strings[1]);
map.put(strings[0],pqt);
}
}
dfs("JFK");
Collections.reverse(list);
return list;
}
public static void dfs(String s){
if (map.containsKey(s) == false){
list.add(s);
return;
}
PriorityQueue<String> pq = map.get(s);
if (pq.size() == 0){
list.add(s);
return;
}else{
while(pq.size() != 0){
dfs(pq.poll());
}
list.add(s);
}
}
}