题目
https://leetcode-cn.com/problems/reconstruct-itinerary/
给定一个机票的字符串二维数组
[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"]。但是它自然排序更大更靠后。
思路
1. 因题目强调了“假定所有机票至少存在一种合理的行程”,所以可利用深搜一定会有结果这一点,无需任何标记、判定,仅单纯对每层进行循环及扣除
2. 这是一个有向图的题目,有图就先建立一个由每个始发地为键,目的地为值组成的列表字典,题目要求“请按字符自然排序返回最小的形成组合”,所以对列表进行倒序排序
3. 准备深搜的堆栈,用于回溯
4. 并且所有地点都要经过,在规划行程中,当某个地点 f 不能去到下一个地方,且还没经过所有地点,就把 f 记录在行程最后,然后回溯到上一个地点进行搜索
代码提交
from typing import List
import collections
class Solution:
def findItinerary(self, tickets: List[List[str]]) -> List[str]:
paths = collections.defaultdict(list) # 由每个始发地为键,目的地为值组成的列表字典
for f, t in tickets: # f, t 分别为from, to,表示机票的始发地和目的地
paths[f].append(t)
for f in paths:
paths[f].sort(reverse=True)
res = []
f_stack = ['JFK'] # dfs所用的堆栈,用于回溯
while f_stack:
f = f_stack[-1]
if paths[f]:
f_stack.append(paths[f].pop()) # 把 t 弹出,并添加到深搜堆栈中,把 t 作为 f 再进行深搜
else:
res.append(f) # 把没有 t 的 f 添加到结果列表
f_stack.pop() # 把没有 t 的 f 从深搜堆栈中弹出
return res[::-1] # 将结果列表倒序输出
S = Solution()
tickets = [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]]
ans = S.findItinerary(tickets)
print(ans)
执行用时:44 ms, 在所有 Python3 提交中击败了95.05%的用户
内存消耗:13.8 MB, 在所有 Python3 提交中击败了96.24%的用户
拓展
- 深度优先搜索 dfs = 堆栈、入栈、出栈
- 广度优先搜索 bfs = 队列、入队、出队