遇到挫折了,暴力回溯超时
代码随想录Carl使用了TreeMap来升序保存每个起始点可以到达的机场以及次数,从字典序最小的开始加入路径做尝试,如果路径不通则return false,通了后续则不用遍历了,相当于做了剪枝操作。
class Solution {
private Deque<String> res;
private Map<String, Map<String, Integer>> map;
private boolean backTracking(int ticketNum){
if(res.size() == ticketNum + 1){
return true;
}
String last = res.getLast();
if(map.containsKey(last)){//防止出现null
for(Map.Entry<String, Integer> target : map.get(last).entrySet()){
int count = target.getValue();
if(count > 0){
res.add(target.getKey());
target.setValue(count - 1);
if(backTracking(ticketNum)) return true;
res.removeLast();
target.setValue(count);
}
}
}
return false;
}
public List<String> findItinerary(List<List<String>> tickets) {
map = new HashMap<String, Map<String, Integer>>();
res = new LinkedList<>();
for(List<String> t : tickets){
Map<String, Integer> temp;
if(map.containsKey(t.get(0))){
temp = map.get(t.get(0));
temp.put(t.get(1), temp.getOrDefault(t.get(1), 0) + 1);
}else{
temp = new TreeMap<>();//升序Map
temp.put(t.get(1), 1);
}
map.put(t.get(0), temp);
}
res.add("JFK");
backTracking(tickets.size());
return new ArrayList<>(res);
}
}
class Solution {
Map<String, PriorityQueue<String>> map = new HashMap<String, PriorityQueue<String>>();
List<String> itinerary = new LinkedList<String>();
public List<String> findItinerary(List<List<String>> tickets) {
for (List<String> ticket : tickets) {
String src = ticket.get(0), dst = ticket.get(1);
if (!map.containsKey(src)) {
map.put(src, new PriorityQueue<String>());
}
map.get(src).offer(dst);
}
dfs("JFK");
Collections.reverse(itinerary);
return itinerary;
}
public void dfs(String curr) {
while (map.containsKey(curr) && map.get(curr).size() > 0) {
String tmp = map.get(curr).poll();
dfs(tmp);
}
itinerary.add(curr);
}
}
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/reconstruct-itinerary/solution/zhong-xin-an-pai-xing-cheng-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
lc上的答案非常精妙啊:
对于当前节点而言,从它的每一个非「死胡同」分支出发进行深度优先搜索,都将会搜回到当前节点。而从它的「死胡同」分支出发进行深度优先搜索将不会搜回到当前节点。也就是说当前节点的死胡同分支将会优先于其他非「死胡同」分支入栈。
这样对于路径上的每个节点都是死胡同的节点先入栈即dfs搜到最底部才是死胡同节点,这个节点会优先加入itinerary,其他节点按照字典序,大的先加入到数组中,最后将数组翻转就行了。