重新安排行程
难度:
标签:
题目描述
给你一份航线列表 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"] 解释:另一种有效的行程是 ["JFK","SFO","ATL","JFK","ATL","SFO"] ,但是它字典排序更大更靠后。
提示:
1 <= tickets.length <= 300
tickets[i].length == 2
fromi.length == 3
toi.length == 3
fromi
和toi
由大写英文字母组成fromi != toi
代码结果
运行时间: 21 ms, 内存: 16.5 MB
/*
* 思路:
* 1. 将所有航班票按照出发地为键,目的地为值放入一个Map中,值为一个优先队列,方便按字典序排序。
* 2. 使用DFS从JFK开始构建行程,每次选择字典序最小的航班。
* 3. 使用LinkedList将行程存储,因为DFS后行程是逆序的,使用LinkedList的addFirst方法可以避免最后反转列表。
*/
import java.util.*;
import java.util.stream.Collectors;
public class SolutionStream {
public List<String> findItinerary(List<List<String>> tickets) {
Map<String, PriorityQueue<String>> flights = tickets.stream()
.collect(Collectors.groupingBy(
ticket -> ticket.get(0),
Collectors.mapping(
ticket -> ticket.get(1),
Collectors.toCollection(PriorityQueue::new)
)
));
LinkedList<String> itinerary = new LinkedList<>();
dfs("JFK", flights, itinerary);
return itinerary;
}
private void dfs(String airport, Map<String, PriorityQueue<String>> flights, LinkedList<String> itinerary) {
PriorityQueue<String> destinations = flights.get(airport);
while (destinations != null && !destinations.isEmpty()) {
dfs(destinations.poll(), flights, itinerary);
}
itinerary.addFirst(airport);
}
}
解释
方法:
The solution uses a depth-first search (DFS) combined with a min-heap for lexical order and a stack to build the itinerary. Initially, it constructs a graph with directed edges from each ticket's departure to its destination, using a defaultdict of lists. Each list is then converted into a min-heap to ensure that the next destination selected is the lexicographically smallest available. Starting from 'JFK', the DFS explores as far as possible along each branch, pushing the airports to the stack once all possible paths from that airport are exhausted. After the DFS completes, the stack holds the itinerary in reverse order, which is then reversed to produce the final itinerary order. This approach inherently handles the backtracking by exploring all possible routes using each ticket exactly once.
时间复杂度:
O(E log m)
空间复杂度:
O(V + E)
代码细节讲解
🦆
为什么在构建图时选择使用最小堆(min-heap)而不是直接排序列表?
▷🦆
在深度优先搜索(DFS)中,如果某条路径被堵塞,算法是如何确保使用所有的机票并找到有效路径的?
▷🦆
您提到在深度优先搜索结束后,栈中的行程是倒序的。这种倒序的原因是什么?
▷🦆
如果某个机场的所有出发航线都已经在之前的路径中使用过,但该机场又被重新访问,这种情况下该如何处理?
▷