开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情
332.重新安排行程
题目分析
题目给出一份航线列表tickets,tickets[i] = [fromi, toi]要求对行程进行重新规划排序。要求行程必须从JFK开始,并且如果存在多种有效行程,按字典排序(行程 ["JFK", "LGA"] 与 ["JFK", "LGB"] 相比就更小)返回最小的行程组合。所有机票有且只能使用一次。
解题
这道题有点像图的深度搜索,但是其中还是用到了回溯的方法,因为回溯才能在路径出错时,继续查找其他的路径。
在回溯遍历的过程中,我们需要知道这个机场下一个可以去哪个机场。所以我们需要建立一个映射关系来理清。
通过建立一个对象结构,将出发地和降落地映射起来。其中降落地用一个数组表示出发地可以降落到的所有机场。
const map = {}
for(const ticket of tickets) {
const [from,to] = ticket
if(!map[from]) {
map[from] = []
}
map[from].push(to)
}
由于需要返回按字典排序的最小行程组合,所以我们在映射关系里就将其排序。
for(const city in map) {
map[city].sort()
}
接下来就可以使用这个进行递归搜索。
递归函数的两个参数分别是当前的城市以及用过的机票数。当第2个参数等于机票数时,代表用光所有的机票,路径已经找到。
const dfs = (city,used) => {
if(used === tickets.length) return true
const nextCities = map[city]
if(!nextCities || nextCities.length === 0) return false
for(let i = 0;i < nextCities.length;i++) {
const next = nextCities[i]
nextCities.splice(i,1)
res.push(next)
if(dfs(next,used + 1)) {
return true
} else {
nextCities.splice(i,0,next)
res.pop()
}
}
}
接下来通过映射结构获取下一站能去的城市,如果还没有用光机票的时候,就没有下一站了,就可以回溯返回。
后记
这道题作为一道困难题困了好久,找了好几个题解都看不懂(应该是我太笨了),不过332. 重新安排行程 - 力扣(Leetcode)这个题解真的很清晰。