[LC] 332. Reconstruct Itinerary

这一题并不是我个人很喜欢的题目类型。最优解基本就是特定的算法,知道就能过,不知道也不是你能短时间里想出来的解决方案。这题就是欧拉路径的题目,给定起点和所有边的信息,在不重复的情况下走完全图。

https://ikely.me/2015/06/28/%E6%AC%A7%E6%8B%89%E8%B7%AF/

https://www.cnblogs.com/KasenBob/p/9985398.html

第一篇文章里的第二种算法以及第二篇文章都是在讲述这一类题目的最优解Hierholzer算法。其实就是一个先建图再dfs遍历图的一个标准的过程。你可以认为这是一个自下而上的遍历。先dfs遍历子节点,然后遍历完之后再把自己放进结果链表的头。就这样从后往前建立结果。根据这个算法,可以得到代码如下:

    public List<String> findItinerary(List<List<String>> tickets) {
        Map<String, PriorityQueue<String>> graph = new HashMap<>();
        for (List<String> ticket : tickets) {
            graph.computeIfAbsent(ticket.get(0), k -> new PriorityQueue<>()).add(ticket.get(1));
        }
        
        LinkedList<String> result = new LinkedList<>();
        dfs(graph, "JFK", result);
        return result;
    }
    
    public void dfs(Map<String, PriorityQueue<String>> graph, String loc, LinkedList<String> result) {
        if (graph.containsKey(loc)) {
            PriorityQueue<String> que = graph.get(loc);
            while(!que.isEmpty()) {
                dfs(graph, que.poll(), result);
            }
        }
        
        result.addFirst(loc);
    }

这里之所以用到了PriorityQueue,是因为要输出smallest lexical order的结果。不然随便一个queue都可以。

另外再给一套代码,算法是一致的。但是用了循环代替递归。

    public List<String> findItinerary(List<List<String>> tickets) {
        Map<String, PriorityQueue<String>> graph = new HashMap<>();
        for (List<String> ticket : tickets) {
            graph.computeIfAbsent(ticket.get(0), k -> new PriorityQueue<>()).add(ticket.get(1));
        }
        
        LinkedList<String> result = new LinkedList<>();
        Stack<String> dfsStk = new Stack<String>();
        dfsStk.push("JFK");
        while (!dfsStk.isEmpty()) {
            String curNode = dfsStk.peek();
            PriorityQueue<String> nextNodes = graph.get(curNode);
            if (nextNodes == null || nextNodes.isEmpty()) {
                dfsStk.pop();
                result.addFirst(curNode);
            } else {
                dfsStk.push(nextNodes.poll());
            }
        }
        return result;
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值