1. 问题描述:
给定一个机票的字符串二维数组 [from, to],子数组中的两个成员分别表示飞机出发和降落的机场地点,对该行程进行重新规划排序。所有这些机票都属于一个从JFK(肯尼迪国际机场)出发的先生,所以该行程必须从 JFK 出发。
说明:
如果存在多种有效的行程,你可以按字符自然排序返回最小的行程组合。例如,行程 ["JFK", "LGA"] 与 ["JFK", "LGB"] 相比就更小,排序更靠前
所有的机场都用三个大写字母表示(机场代码)。
假定所有机票至少存在一种合理的行程。
示例 1:
输入: [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]]
输出: ["JFK", "MUC", "LHR", "SFO", "SJC"]
示例 2:
输入: [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
输出: ["JFK","ATL","JFK","SFO","ATL","SFO"]
解释: 另一种有效的行程是 ["JFK","SFO","ATL","JFK","ATL","SFO"]。但是它自然排序更大更靠后。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reconstruct-itinerary
2. 思路分析:
① 看到题目会想到使用普通模拟的思路可以解决,因为我们可以把这些字符串放到map中,这样在取出字符串的话就会很方便,因为题目中要求字典序最小的,所以可以对map中映射的值进行排序,然后模拟整个过程即可,但是这个想法还是存在一定漏洞的,因为有可能字典序较小的是不合理的行程,比如像这个数据[["JFK","KUL"],["JFK","NRT"],["NRT","JFK"]]字典序较小的起点为[["JFK","KUL"]但是这个并不是合理的,所以不能够使用这样的方法来解决
② 所以首先需要解决一个问题是map中的数据映射,其实放到map中比较简单,关键是对map中的字符串类型进行排序,一开始的时候使用的是Deque来放字符串但是发现没有对Deque的String类型排序的方法,后面在题解中发现可以使用List来放置字符串,因为使用List类型可以对List的String类型使用java 8语法来进行排序,先是要取出map的值然后使用forEach方法对其遍历,里面传入排序的对象,后面是对象中的什么方法来进行排序
③ 因为存在不确定性的尝试,所以可以使用dfs来解决,使用dfs来解决的话还有一个特点是能够走完所有的行程并且还有一个优点是可以利用dfs层层返回的这个特点来添加终点,因为在①中说到字典序最小的行程并不一定是合理的所以这个时候不能够在递归前来添加终点否则有的结果是错误的,比如像[["JFK","KUL"],["JFK","NRT"],["NRT","JFK"]]这个数据,而在dfs调用之后添加终点恰恰可以解决这个问题,因为每一次递归调用都会先把合理的行程先添加上去,比如上面这个数据一开始递归调用先是[["JFK","KUL"],这个起点发现走不下去了,尝试另外一个起点["JFK","NRT"],发现存在另外一条可行的路径,最终在返回的时候先将后面这路径先添加到结果中JFK, NRT然后再添加上一开始的KUL这样的结果才是正确的,通常我们在写dfs代码的时候可能根据具体的情况在递归之前处理或者是递归调用之后处理来获取某些值,这个是我们在使用dfs解决问题的时候需要处理的点和学会的一个点
3. 代码如下:
import java.util.*;
class Solution {
List<String> res = new ArrayList<>();
public List<String> findItinerary(List<List<String>> tickets) {
Map<String, List<String>> map = new HashMap();
for (List<String> list : tickets){
/*使用getOrDefault方法很方便因为假如之前没有当前的键那么就新建假如有就获取之前的值*/
List<String> li = map.getOrDefault(list.get(0), new ArrayList<String>());
li.add(list.get(1));
map.put(list.get(0), li);
}
/*使用java8的语法进行排序*/
map.values().forEach(x -> x.sort(String::compareTo));
dfs(tickets, "JFK", map);
return res;
}
private void dfs(List<List<String>> tickets, String start, Map<String, List<String>> map) {
List<String> list = map.get(start);
while (list != null && list.size() > 0){
dfs(tickets, list.remove(0), map);
}
/*返回的时候添加终点: 这一句代码是核心因为正着插的时候会导致: ["JFK","KUL","NRT","JFK"]数据出现错误*/
res.add(0, start);
}
}