leetcode *332. 重新安排行程(欧拉回路 / 欧拉通路)

【题目】*332. 重新安排行程

753. 破解保险箱

给定一个机票的字符串二维数组 [from, to],子数组中的两个成员分别表示飞机出发和降落的机场地点,对该行程进行重新规划排序。所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发的先生,所以该行程必须从 JFK 开始。

说明:
如果存在多种有效的行程,你可以按字符自然排序返回最小的行程组合。例如,行程 [“JFK”, “LGA”] 与 [“JFK”, “LGB”] 相比就更小,排序更靠前
所有的机场都用三个大写字母表示(机场代码)。
假定所有机票至少存在一种合理的行程。
示例 1:

输入: [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]]
输出: ["JFK", "MUC", "LHR", "SFO", "SJC"]

示例 2:

输入: [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
输出: ["JFK","ATL","JFK","SFO","ATL","SFO"]
解释: 另一种有效的行程是 ["JFK","SFO","ATL","JFK","ATL","SFO"]。但是它自然排序更大更靠后。

【解题思路1】Hierholzer 算法

  1. 由于题目中说必然存在一条有效路径(至少是半欧拉图),所以算法不需要回溯(既加入到结果集里的元素不需要删除)
  2. 整个图最多存在一个死胡同(出度和入度相差1),且这个死胡同一定是最后一个访问到的,否则无法完成一笔画。
  3. DFS的调用其实是一个拆边的过程(既每次调用删除一条边),一定是递归到这个死胡同(无边可拆)后递归函数开始返回。所以死胡同是第一个加入栈中的元素。
  4. 最后逆序的输出即可。

Hierholzer 算法用于在连通图中寻找欧拉路径,其流程如下:

  • 从起点出发,进行深度优先搜索。
  • 每次沿着某条边从某个顶点移动到另外一个顶点的时候,都需要删除这条边。
  • 如果没有可移动的路径,则将所在节点加入到栈中,并返回。

当顺序地考虑该问题时,也许很难解决该问题,因为无法判断当前节点的哪一个分支是「死胡同」分支。
不妨倒过来思考。只有那个入度与出度差为 1 的节点会导致死胡同。而该节点必然是最后一个遍历到的节点。可以改变入栈的规则,当遍历完一个节点所连的所有节点后,才将该节点入栈(即逆序入栈)。
对于当前节点而言,从它的每一个非「死胡同」分支出发进行深度优先搜索,都将会搜回到当前节点。而从它的「死胡同」分支出发进行深度优先搜索将不会搜回到当前节点。也就是说当前节点的死胡同分支将会优先于其他非「死胡同」分支入栈。
这样就能保证可以「一笔画」地走完所有边,最终的栈中逆序地保存了「一笔画」的结果。只要将栈中的内容反转,即可得到答案。

class Solution {
    
    
    Map<String, PriorityQueue<String>> map = new HashMap<String, PriorityQueue<String>>();
    List<String> itinerary = new LinkedList<String>();

    public List<String> findItinerary(List<List<String>> tickets) {
    
    
        for (List<String> ticket : tickets) {
    
    
            String src = ticket.get(0), dst = ticket.get(1);
            if (!map.containsKey(src)) {
    
    
                map.put(src, new PriorityQueue<String>());
            }
            map.get(src).offer(dst);
        }
        dfs("JFK");
        Collections.reverse(itinerary);
        return itinerary;
    }

    public void dfs(String curr) {
    
    
        while (map.containsKey(curr) && map.get(curr).size() > 0) {
    
    
            String tmp = map.get(curr).poll();
            dfs(tmp);
        }
        itinerary.add(curr);
    }
}

猜你喜欢

转载自blog.csdn.net/XunCiy/article/details/108257295