leetcode332. 重新安排行程

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

说明:

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

示例 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"]。但是它自然排序更大更靠后。

 

这个题看到了一脸懵逼,然后记录一下搜索的结果:

思路:最初的思路是top down的DFS,就是直接正向搜出正确路径,这样需要回朔状态,需要的时间复杂度很大.所以并不能过掉数据量大的数据.

看了别人的思路,基本是bottom up的DFS,就是路径是反向从最低层往上得出的.

将所有的机票用hash表保存起来,最后我们就是要找出一条路径将机票用完,并且如果有多条路径,就找字典序最小的.

我们可以构造一个hash表,key为一个地点字符串,value为一个multiset保存这个地点可以飞到的其他地方,之所以用multiset而不是set是因为从一个地方可以去别的地方几次.

并且这个数据结构是可以将数据排序的,方便我们有序的取数据.

然后我们利用DFS思想从"JFK"机场出发,按照字典序从小到达取与其连接的地点,从下一个地点再递归的搜索,直到没有和某地点相连的机票的了.我们就到达了最底层,然后往上返回路径即可.
--------------------- 
作者:小榕流光 
来源:CSDN 
原文:https://blog.csdn.net/qq508618087/article/details/51375040 
版权声明:本文为博主原创文章,转载请附上博文链接!

https://blog.csdn.net/zxzxzx0119/article/details/85772702

解析

  • 由于必须要按照字典序最小的来访问某个结点的孩子,所以在查找节点的孩子的map中使用一个优先队列存放,每次取出来的是字典序最小的;

  • 然后按照类似后序遍历的顺序遍历这个图(先访问自己孩子,然后访问自己),然后在反转过来,这样可以得到正确的答案;

  • 也可以理解为dfs的时候,是先访问自己的孩子,然后访问自己,最后将访问的顺序翻转过来即可,需要注意的时候一定要使用后序的方式,不然会在选择的时候出错(或者说不能正确访问所有的结点);

å¨è¿éæå¥å¾çæè¿°

题意及分析:将所有的机票用数组保存起来,最后我们就是要找出一条路径将机票用完,并且如果有多条路径,就找字典序最小的。最开始想到的方法是用一个hashmap<String,PriorityQueue<String>>保存每个点及其邻节点,然后使用深度遍历,第一次得到的结果便是答案(因为每次都是用的最小路径)。 另外一种方法是每次找到终点,然后删除该点继续查找下一个终点,最后得到的结果反转即可。

实际上,这道题目是计算最小的欧拉路径。通过分析可以知道:

如果一个有向图,存在欧拉路径(不是欧拉回路),那么图中的点最多只可能有两个点:degree(入)!=degree(出),并且这两个点,一个入度>出度,一个入度<出度;也有可能所有点degree(入)==degree(出),则存在欧拉回路

很明显,既然题目保证存在欧拉路径,那么JFK就是那个入度<出度的点,并且存在一个点入度>出度;或者所有点入度==出度

贪心法:从JFK开始,每次选取最小路径走,如果走不下去,只有可能遇到了终结点PP(那个入度>出度的点),这样就形成了从JFK到PP的主路径。剩下没走的边只有可能形成环,只要将环并入到主路径上就完成了最小欧拉路径的搜索!!

public class Solution {
    Map<String, PriorityQueue<String>>  map= new HashMap<>();
    List<String> res = new ArrayList<>();

    public List<String> findItinerary(String[][] tickets) {
        for(String[] ticket:tickets){
            map.computeIfAbsent(ticket[0],k->new PriorityQueue<>()).add(ticket[1]);
        }
        dfs("JFK");
        Collections.reverse(res);
        return res;
    }

    public void dfs(String node){
        PriorityQueue<String> priorityQueue = map.get(node);
        while(priorityQueue!=null&&!priorityQueue.isEmpty())
            dfs(priorityQueue.poll());
        res.add(node);
    }
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值