力扣332题(重新安排行程)
332.重新安排行程
基本思想:
回溯
具体实现:
1.记录映射关系
Map<String, Map<String, Integer>> map 记录航班的映射关系
<出发机场,Map<到达机场,航班次数>>
航班次数做相应的增减,标记到达机场是否使用过了
如果“航班次数”大于零,说明目的地还可以飞,
如果“航班次数”等于零说明目的地不能飞了,而不用对集合做删除元素或者增加元素的操作。
ticketNum,表示有多少个航班(终止条件会用上)
2.递归返回参数
boolean,
一般函数返回值都是void,这次为什么是bool呢?
因为只需要找到一个行程,就是在树形结构中唯一的一条通向叶子节点的路线
所以找到了这个叶子节点了直接返回
3.递归终止条件
回溯遍历的过程中,遇到的机场个数,如果达到了(航班数量+1),
那么就找到了一个行程,把所有航班串在一起了。
4.单层搜索的逻辑
通过Map<String, Map<String, Integer>> map 中的Integer来判断 这个集合里的机场是否使用过,
这样避免了直接去删元素。
代码:
class Solution { private Deque<String> res; private Map<String, Map<String, Integer>> map;//<出发机场, 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))){//map中包含遍历到的出发机场 temp = map.get(t.get(0));//该出发机场对应的<到达机场,航班次数>赋给temp temp.put(t.get(1), temp.getOrDefault(t.get(1), 0) + 1); //添加temp<到达机场,航班次数> }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); } }