T: O(E^d) , E number of filghts (edges), d is the branch numbers of each backtracking
```java
class Solution {
public List<String> findItinerary(List<List<String>> tickets) {
Map<String, Map<String, Integer>> graph = buildGraph(tickets);
return dfs("JFK", graph); // start point is "JFK"
}
private List<String> dfs(String start, Map<String, Map<String, Integer>> graph) {
if (graph.isEmpty()) { // when no nodes on graph, just return with start
return new ArrayList<>(Arrays.asList(start));
}
List<String> next = new ArrayList<>(graph.getOrDefault(start, new HashMap<>()).keySet());
Collections.sort(next); // sort (for smallest lexical order)
for (String nxt : next) {
removeNode(start, nxt, graph); // backtracking
List<String> result = dfs(nxt, graph);
addNode(start, nxt, graph); // backtracking
if (result != null) { // always add start in the beginning
result.add(0, start);
return result;
}
}
return null;
}
private Map<String, Map<String, Integer>> buildGraph(List<List<String>> tickets) {
Map<String, Map<String, Integer>> graph = new HashMap<>();
for (List<String> t : tickets) {
String from = t.get(0);
String to = t.get(1);
addNode(from, to, graph);
}
return graph;
}
private void addNode(String from, String to, Map<String, Map<String, Integer>> graph) {
graph.putIfAbsent(from, new HashMap<>());
Map<String, Integer> map = graph.get(from);
map.put(to, map.getOrDefault(to, 0) + 1);
}
private void removeNode(String from, String to, Map<String, Map<String, Integer>> graph) {
Map<String, Integer> map = graph.get(from);
map.put(to, map.getOrDefault(to, 0) - 1);
if (map.get(to) == 0) {
map.remove(to);
}
if (graph.get(from).isEmpty()) {
graph.remove(from);
}
}
}
```
可以大幅減少重複 case 去計算, 以 "ATL", "AAA" 重複了這麼多次, 我們只需要 add, remove backtracking 一次就可以達到效果