332. Reconstruct Itinerary
ref: https://leetcode.com/problems/reconstruct-itinerary/
Given a list of airline tickets represented by pairs of departure and arrival airports [from, to]
, reconstruct the itinerary in order. All of the tickets belong to a man who departs from JFK
. Thus, the itinerary must begin with JFK
.
Note:
- If there are multiple valid itineraries, you should return the itinerary that has the smallest lexical order when read as a single string. For example, the itinerary
["JFK", "LGA"]
has a smaller lexical order than["JFK", "LGB"]
. - All airports are represented by three capital letters (IATA code).
- You may assume all tickets form at least one valid itinerary.
Example 1:tickets
= [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]]
Return ["JFK", "MUC", "LHR", "SFO", "SJC"]
.
Example 2:tickets
= [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
Return ["JFK","ATL","JFK","SFO","ATL","SFO"]
.
Another possible reconstruction is ["JFK","SFO","ATL","JFK","ATL","SFO"]
. But it is larger in lexical order.
首先感觉就是普通的backtracking(dfs),但是写的时候疯狂在corner case报错
问题出在,
1. 比如jfk->sfo,还可以有jfk->atl,还可以有sfo->jfk,就是说可以有同一段旅程好几次倒腾,但是如果只是用普通的map的话,很难检测出重复的票。
2. 如果用tickets[][]里面的index表示的话,每次对tickets从头到尾找一遍太慢了,会tle
所以有一个答案写得很好: https://discuss.leetcode.com/topic/36721/short-c-dfs-iterative-44ms-solution-with-explanation-no-recursive-calls-no-backtracking/3
这个里面的点:
1. 我认为这道题的特别之处是,我知道这个不会有死路,就是这些机票确定是肯定是对的,只要沿着<from, to>走,就一定是对的,但是只是可能不是Lexical order上的最优,所以我认为不存在wrong path要回退
2. 用map<String, PriorityQueue<Stiring>>来实现同一个站greedy的走法,只要找到头了,就是对的
还有一点自己的, 就是看到有人留言说Stack这个已经被Java官方标记成的deprecated的类了,官方现在对于queue和stack建议统一使用Deque。
stack中的push() => offerFirst(). pop() => pollFirst(), peek()=> peekFirst()
queue中的 add() => offerLast(), remove() => pollFirst(), peek() => peekFirst()
我省略了add/remove一组,直接用offer/poll,第一组也存在,此处不写
1 public List<String> findItinerary(String[][] tickets) { 2 List<String> res = new ArrayList<String>(); 3 if(tickets.length == 0 || tickets[0].length == 0) { 4 return res; 5 } 6 Map<String, PriorityQueue<String>> map = new HashMap<>(); 7 for(int i = 0; i < tickets.length; i++) { 8 if(map.containsKey(tickets[i][0])) { 9 map.get(tickets[i][0]).add(tickets[i][1]); 10 } else { 11 PriorityQueue<String> pq = new PriorityQueue<>(); 12 pq.offer(tickets[i][1]); 13 map.put(tickets[i][0], pq); 14 } 15 } 16 Deque<String> stack = new ArrayDeque<>(); 17 stack.offerFirst("JFK"); 18 while(!stack.isEmpty()) { 19 String next = stack.peekFirst(); 20 if(map.containsKey(next) && !map.get(next).isEmpty()) { 21 stack.offerFirst(map.get(next).poll()); 22 } else { 23 res.add(stack.pollFirst()); 24 } 25 } 26 Collections.reverse(res); 27 return res; 28 }