05 August 2008
Given a list of airline tickets represented by pairs of departure and arrival airports
, reconstruct the itinerary in order. All of the tickets belong to a man who departs from 1
[from, to]
. Thus, the itinerary must begin with 1
JFK
.1
JFK
Note:
1
["JFK", "LGA"]
has a smaller lexical order than 1
["JFK", "LGB"]
.Example 1:
1
2
Input: [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]]
Output: ["JFK", "MUC", "LHR", "SFO", "SJC"]
Example 2:
1
2
3
4
Input: [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
Output: ["JFK","ATL","JFK","SFO","ATL","SFO"]
Explanation: Another possible reconstruction is ["JFK","SFO","ATL","JFK","ATL","SFO"].
But it is larger in lexical order.
DFS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.util.*;
class Solution {
public List<String> findItinerary(List<List<String>> tickets) {
// 因为逆序插入,所以用链表
List<String> ans = new LinkedList<>();
if (tickets == null || tickets.size() == 0)
return ans;
Map<String, List<String>> graph = new HashMap<>();
for (List<String> pair : tickets) {
// 因为涉及删除操作,我们用链表
List<String> nbr = graph.computeIfAbsent(pair.get(0), k -> new LinkedList<>());
nbr.add(pair.get(1));
}
// 按目的顶点排序
graph.values().forEach(x -> x.sort(String::compareTo));
visit(graph, "JFK", ans);
return ans;
}
// DFS方式遍历图,当走到不能走为止,再将节点加入到答案
private void visit(Map<String, List<String>> graph, String src, List<String> ans) {
List<String> nbr = graph.get(src);
while (nbr != null && nbr.size() > 0) {
String dest = nbr.remove(0);
visit(graph, dest, ans);
}
ans.add(0, src); // 逆序插入
}
}
也可以不对临接点排序,而是使用小顶堆(Java可以用优先队列)。这样我们删除边的操作和访问最小字典顺序顶点可以用出队操作代替,时间复杂度应该会比排序再删除要低一些。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.util.*;
class Solution {
public List<String> findItinerary(List<List<String>> tickets) {
// 因为逆序插入,所以用链表
List<String> ans = new LinkedList<>();
if (tickets == null || tickets.size() == 0)
return ans;
Map<String, PriorityQueue<String>> graph = new HashMap<>();
for (List<String> pair : tickets) {
// 因为涉及删除操作,我们用链表
PriorityQueue<String> nbr = graph.computeIfAbsent(pair.get(0), k -> new PriorityQueue<>());
nbr.add(pair.get(1));
}
visit(graph, "JFK", ans);
return ans;
}
// DFS方式遍历图,当走到不能走为止,再将节点加入到答案
private void visit(Map<String, PriorityQueue<String>> graph, String src, List<String> ans) {
PriorityQueue<String> nbr = graph.get(src);
while (nbr != null && nbr.size() > 0) {
String dest = nbr.poll();
visit(graph, dest, ans);
}
ans.add(0, src); // 逆序插入
}
}