LeetCode332 Reconstruct Itinerary

find the smallest lexicographic order of a valid plane tickets order starting from “JFK”

In graph theory, an Eulerian trail (or Eulerian path) is a trail in a finite graph that visits every edge exactly once (allowing for revisiting vertices).
so the problem is actually a variant of Eulerian path, with a fixed starting point.

and we have a algorithm used to solve this kind of problem, it is called Hierholzer algorithm.
so the algorithm consist of two steps:
It starts with a random node and then follows an arbitrary unvisited edge to a neighbor. This step is repeated until one returns to the starting node. This yields a first circle in the graph.
If this circle covers all nodes it is an Eulerian cycle and the algorithm is finished. Otherwise, one chooses another node among the cycles’ nodes with unvisited edges and constructs another circle, called subtour.
By connecting all the circles in the above process, we build the Eulerian cycle at the end.
//but in the solutions , we didn;t really use that algorithm:

class Solution {
  // origin -> list of destinations
  HashMap<String, LinkedList<String>> flightMap = new HashMap<>();
  LinkedList<String> result = new LinkedList<String>();

  public List<String> findItinerary(List<List<String>> tickets) {
    // Step 1). build the graph first, all origin as keys, and all its destination as values. since there are multiple destination for the same origin. or it can be 
    for (List<String> ticket: tickets) {
        flightMap.put(ticket.get(0), new LinkedList<>());
    }
    for (List<String> ticket: tickets) {
        flightMap.get(ticket.get(0)).add(ticket.get(1));
    }

    // Step 2). order the destinations
    flightMap.forEach((key, value) -> Collections.sort(value)); //inner sort the values based on lexicographic

    // Step 3). post-order DFS
    DFS("JFK");
    return result;
  }

  private void DFS(String origin) {
    // Visit all the outgoing edges first.
    
    if (flightMap.containsKey(origin)) {
      
      LinkedList<String> destList = flightMap.get(origin);
      while (!destList.isEmpty()) {
        // while we visit the edge, we trim it off from graph.
        String dest = destList.removeFirst(); //pull the first one which is the smallest lexicograph
        DFS(dest);
      }
    }
    // add the airport to the head of the itinerary
    result.addFirst(origin); //we can't put it inthe if statement because if so we may miss the last place since it is a destination and did not contains in flightMap.keySet(). and it can not writen in result.add(origin) and place it in the front like preorder dfs
  }
}

the code is pretty simply actually, just constrcut the map, and then do a dfs starting at the given “JFK”. and the dfs function is just a simple postorder.
and there is only place i don’t undetstand, why can’t we use:

private void DFS(String origin) {
    // Visit all the outgoing edges first.
    
    if (flightMap.containsKey(origin)) {
      result.add(origin); <=====change it to here
      LinkedList<String> destList = flightMap.get(origin);
      while (!destList.isEmpty()) {
        // while we visit the edge, we trim it off from graph.
        String dest = destList.removeFirst(); //pull the first one which is the smallest lexicograph
        DFS(dest);
      }
    }
   
  }
posted @ 2020-05-10 04:08  EvanMeetTheWorld  阅读(16)  评论(0)    收藏  举报