332. Reconstruct Itinerary
332. 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.
This is about edge traversal in a cyclic graph. Course schedule is about vertices traversal.
Solution: just traverse from the first node downward, and figure out a way to merge different pieces of routes.
public class Solution { public List<String> findItinerary(String[][] tickets) { LinkedList<String> ret = new LinkedList<String>(); if(tickets == null) return ret; Map<String, PriorityQueue<String>> map = new HashMap<String, PriorityQueue<String>>(); for(String[] ticket: tickets) { String from = ticket[0]; String to = ticket[1]; PriorityQueue<String> destinations = map.get(from); if(destinations == null) { destinations = new PriorityQueue<String>(); map.put(from, destinations); } destinations.add(to); } LinkedList<String> tail = new LinkedList<String>(); dfs("JFK", map, ret, tail); ret.addAll(tail); return ret; } //Think through the following cases //1. a->b->c->a->d //2. a->c->d->a->b //3. a->c->e->f->c->d->a->b private void dfs(String node, Map<String, PriorityQueue<String>> map, Deque<String> ret, Deque<String> tail) { ret.add(node); PriorityQueue<String> dests = map.get(node); while(dests!=null && !dests.isEmpty()){ String dest = dests.poll(); dfs(dest, map, ret, tail); if(!dests.isEmpty()){ //If we have more dests, it means part of route should be traversed at the end. //Or in other words, insert another route in the middle. while(ret.peekLast()!=node){ tail.push(ret.removeLast()); } } } } }
This implementation is based on Hierholzer's algorithm. More readings at https://en.wikipedia.org/wiki/Eulerian_path
public class Solution { public List<String> findItinerary(String[][] tickets) { List<String> ret = new ArrayList<String>(); if(tickets == null) return ret; Map<String, PriorityQueue<String>> map = new HashMap<String, PriorityQueue<String>>(); for(String[] ticket: tickets) { String from = ticket[0]; String to = ticket[1]; PriorityQueue<String> destinations = map.get(from); if(destinations == null) { destinations = new PriorityQueue<String>(); map.put(from, destinations); } destinations.add(to); } dfs("JFK", map, ret); Collections.reverse(ret); return ret; } private void dfs(String node, Map<String, PriorityQueue<String>> map, List<String> ret) { PriorityQueue<String> destinations = map.get(node); while(destinations != null && !destinations.isEmpty()) { String next = destinations.remove(); dfs(next, map, ret); } ret.add(node); } }

浙公网安备 33010602011771号