LeetCode 332. 重新安排行程
阿新 • • 發佈:2020-08-27
題目連結
思路分析
這個題很明顯的是一個圖論,題目在給定一個起點的前提下,讓我們尋找一條路徑 ,能夠把當前圖中所有的邊都走一次,而且這個圖還是個有向圖。
那麼本菜雞隻能想到最原始的方法
- 先根據輸入資料建立鄰接連結串列
- 對所有的鄰接連結串列進行排序,因為我們需要按照字典序的順序來訪問邊。
- 使用鄰接連結串列進行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; } }