代码随想录第三十天 | 332.重新安排行程

87 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情

332.重新安排行程

题目分析

题目给出一份航线列表ticketstickets[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)这个题解真的很清晰。