zoukankan      html  css  js  c++  java
  • Leetcode: 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 may 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.

    refer to Recursion https://leetcode.com/discuss/84702/share-my-solution

    and Iteration https://leetcode.com/discuss/84706/share-solution-java-greedy-stack-15ms-with-explanation

    Explanation https://leetcode.com/discuss/84659/short-ruby-python-java-c

    enter image description here

    这一道题不能用Topological sort是因为topological sort只能在DAG(A指Acyclic)里面找出一条路径,而这里只是directed graph, 环是可能存在的

    Eulerian Path

    This problem is to find Eulerian path. Greedy DFS, building the route backwards when retreating.

    所以应该找Eulerian Path(visit each edge exactly once), 因为题目说了all tickets form at least one valid itinerary. 所以Eulerian Path一定是存在的

    所以,start from JFK, 我们用Hierholzer's algorithm来找Eulerian Path

    Eulerian Path可能不是唯一的, 比如上图有两条:JFK-D-A-C-D-B-C-JFK-A 以及 JFK-A-C-D-B-C-JFK-D-A

    因为题目限制了lexical order,所以找出来应该是第二条,用一个heap来实现有多个邻居选择的时候优先选择哪一个

    下面是重点:greedy的Hierholzer's algorithm

    First keep going forward until you get stuck. Put the stuck element always at the front of the result list(stuck element将会在我们最后的eulerian path的尾部,也就是最后走到这里去,因为先走到这里去会stuck). Try if it is possible to travel to other places from the airport on the way.

    From JFK we first visit JFK -> A -> C -> D -> A. There we're stuck, so we write down A as the end of the route and retreat back to D. There we see the unused ticket to B and follow it: D -> B -> C -> JFK -> D. Then we're stuck again (because D->A has been polled), retreat and write down the airports while doing so: Write down D before A, then JFK before D, the c before JFK, etc. When we're back from our cycle at D, the written route is D -> B -> C -> JFK -> D -> A. Then we retreat further along the original path, prepending C, A and finally JFK to the route, ending up with the route JFK -> A -> C -> D -> B -> C -> JFK -> D -> A.

    Since the problem asks for lexical order smallest solution, we can put the neighbors in a min-heap. In this way, we always visit the smallest possible neighbor first in our trip.

    Use LinkedList as the result type because we always add at the front of the list

     1 public class Solution {
     2     LinkedList<String> res;
     3     Map<String, PriorityQueue<String>> mp;
     4     
     5     public List<String> findItinerary(String[][] tickets) {
     6         if (tickets==null || tickets.length==0) return new LinkedList<String>();
     7         res = new LinkedList<String>();
     8         mp = new HashMap<String, PriorityQueue<String>>();
     9         for (String[] ticket : tickets) {
    10             if (!mp.containsKey(ticket[0])) {
    11                 mp.put(ticket[0], new PriorityQueue<String>());
    12             }
    13             mp.get(ticket[0]).offer(ticket[1]);
    14         }
    15         dfs("JFK");
    16         return res;
    17     }
    18     
    19     public void dfs(String cur) {
    20         while (mp.containsKey(cur) && !mp.get(cur).isEmpty()) {
    21             dfs(mp.get(cur).poll());
    22         }
    23         res.addFirst(cur);
    24     }
    25 }
  • 相关阅读:
    Java synchronized对象级别与类级别的同步锁
    java并发编程JUC第十二篇:AtomicInteger原子整型
    java并发编程JUC第十一篇:如何在线程之间进行对等数据交换
    java并发编程JUC第十篇:CyclicBarrier线程同步
    java并发编程JUC第九篇:CountDownLatch线程同步
    java并发编程工具类JUC第八篇:ConcurrentHashMap
    分享Sql性能优化的一些建议
    java并发编程工具类JUC第七篇:BlockingDeque双端阻塞队列
    java并发编程工具类JUC第六篇:SynchronousQueue同步队列
    java并发编程工具类JUC第五篇:PriorityBlockingQueue优先级队列
  • 原文地址:https://www.cnblogs.com/EdwardLiu/p/5184961.html
Copyright © 2011-2022 走看看