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:

  1. 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"].
  2. All airports are represented by three capital letters (IATA code).
  3. 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); 
    }
}

 

 
posted @ 2016-03-07 05:42  新一代的天皇巨星  阅读(353)  评论(0)    收藏  举报