1. 程式人生 > 實用技巧 >LeetCode 332. 重新安排行程

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;
    }
}