LeetCode 332. 重新安排行程

题目链接

332. 重新安排行程

思路分析

这个题很明显的是一个图论,题目在给定一个起点的前提下,让我们寻找一条路径 ,能够把当前图中所有的边都走一次,而且这个图还是个有向图。
那么本菜鸡只能想到最原始的方法

  1. 先根据输入数据建立邻接链表
  2. 对所有的邻接链表进行排序,因为我们需要按照字典序的顺序来访问边。
  3. 使用邻接链表进行dfs

但是这样做需要有几个问题进行考虑:

  • 如果某个字典序在前面的边所到达的结点的出度为0,我们需要放弃这条路径,寻找下一条边。
  • 有可能出现空指针的问题,这里我们需要加多一重判断。

算法实现

class Solution {
    public List<String> findItinerary(List<List<String>> tickets) {
        HashMap<String, List<String>> map = new HashMap<>();
//进行邻接链表的建立
        for (List<String> temp : tickets) {
            String key = temp.get(0);
            if(!map.containsKey(key)) {
                List<String> target = new LinkedList<String>();
                map.put(key, target);
            }
            map.get(key).add(temp.get(1));
        }
//进行排序,满足题目意思(这里也可以使用优先队列进行邻接点处理,就少一重排序的步骤)
        for(String key: map.keySet()){
            Collections.sort(map.get(key));
        }
        List<String> res = new ArrayList<>();
//把起始点设置为JFK
        res.add("JFK");
        backTracking(map, res, tickets.size() + 1);
        return res;
    }

    private boolean backTracking(HashMap<String, List<String>> map, List<String> res, int targetSize){
        if(res.size() == targetSize){
            return true;
        }
//取出上一条边所到达的终点,我们本次旅行以此为起点
        String last = res.get(res.size() - 1);
        List<String> target = map.get(last);
//防止空指针出现
        if(target == null){
            return false;
        }
//回溯去寻找一条可以把所有边走一遍的路径
        for(int i = 0; i < target.size(); i++){
            String to = target.remove(i);
            res.add(to);
            if(backTracking(map, res, targetSize)){
                return true;
            }
            target.add(i, to);
            res.remove(res.size() - 1);
        }
        return false;
    }
}
posted @ 2020-08-27 10:41  ZJPang  阅读(112)  评论(0编辑  收藏  举报