332. 重新安排行程
题目描述
给你一份航线列表 tickets ,其中 tickets[i] = [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。
所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发的先生,所以该行程必须从 JFK 开始。如果存在多种有效的行程,请你按字典排序返回最小的行程组合。
例如,行程 [“JFK”, “LGA”] 与 [“JFK”, “LGB”] 相比就更小,排序更靠前。
假定所有机票至少存在一种合理的行程。且所有的机票 必须都用一次 且 只能用一次。
示例1:
输入:tickets = [[“MUC”,“LHR”],[“JFK”,“MUC”],[“SFO”,“SJC”],[“LHR”,“SFO”]]
输出:[“JFK”,“MUC”,“LHR”,“SFO”,“SJC”]
示例2:
输入:tickets = [[“JFK”,“SFO”],[“JFK”,“ATL”],[“SFO”,“ATL”],[“ATL”,“JFK”],[“ATL”,“SFO”]]
输出:[“JFK”,“ATL”,“JFK”,“SFO”,“ATL”,“SFO”]
提示:
- 1 <= tickets.length <= 300
- tickets[i].length == 2
- fromi.length == 3
- toi.length == 3
- fromi 和 toi 由大写英文字母组成
- fromi != toi
题解
思路
- 这道题目应该算是深度搜索的题目,但是可以用回溯的方式去解决
- 所以不难写出以下代码
class Solution {
List<String> res;
List<String> path;
public List<String> findItinerary(List<List<String>> tickets) {
res = new ArrayList<>();
path = new ArrayList<>();
tickets.sort((a, b) -> a.get(1).compareTo(b.get(1)));
path.add("JFK");
backTracking(tickets, new boolean[tickets.size()]);
return res;
}
public boolean backTracking(List<List<String>> tickets, boolean[] used) {
if (path.size() == tickets.size() + 1) {
res = new ArrayList<>(path);
return true;
}
for (int i = 0; i < tickets.size(); i++) {
if (used[i]) {
continue;
}
if (tickets.get(i).get(0).equals(path.get(path.size() - 1))) {
used[i] = true;
path.add(tickets.get(i).get(1));
if (backTracking(tickets, used))
return true;
used[i] = false;
path.remove(path.size() - 1);
}
}
return false;
}
}
- 但是这个代码最终是没办法通过leetcode的,会超时,因为这里再单层的逻辑中,是通过遍历整个数组来,查找机票,所以当机票数量非常大的时候,所带来的时间复杂度非常高
- 所以就会引出下面的解法, 先将这种数组的形式,转化成Map的形式
Map<String, Map<String, Integer>>>
转化成这种形式Map<起始站, Map<终点站, 剩余票数>>>
将其记录成这种形式之后,就可以方便查找了
代码
class Solution {
List<String> res;
Map<String, Map<String, Integer>> map;
public List<String> findItinerary(List<List<String>> tickets) {
res = new ArrayList<>();
map = new HashMap<>();
for (List<String> ticket : tickets) {
map.putIfAbsent(ticket.get(0), new TreeMap<>());
map.get(ticket.get(0)).put(ticket.get(1), map.get(ticket.get(0)).getOrDefault(ticket.get(1), 0) + 1);
}
res.add("JFK");
backTracking(tickets.size());
return res;
}
public boolean backTracking(int ticketsNum) {
if (ticketsNum + 1 == res.size())
return true;
String curr = res.get(res.size() - 1);
if (map.containsKey(curr)) {
for (Map.Entry<String, Integer> target : map.get(curr).entrySet()) {
if(target.getValue() > 0){
res.add(target.getKey());
target.setValue(target.getValue() - 1);
if(backTracking(ticketsNum))
return true;
res.remove(res.size() - 1);
target.setValue(target.getValue() + 1);
}
}
}
return false;
}
}