LeetCode 332. 重新安排行程
题目链接
思路分析
这个题很明显的是一个图论,题目在给定一个起点的前提下,让我们寻找一条路径 ,能够把当前图中所有的边都走一次,而且这个图还是个有向图。
那么本菜鸡只能想到最原始的方法
- 先根据输入数据建立邻接链表
- 对所有的邻接链表进行排序,因为我们需要按照字典序的顺序来访问边。
- 使用邻接链表进行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;
}
}