332. 重新安排行程

在这里插入图片描述

思路:
方法一:dfs加回溯
class Solution:
    def findItinerary(self, tickets: List[List[str]]) -> List[str]:
        from collections import defaultdict
        graph = defaultdict(list)
        for i in tickets:
            graph[i[0]].append(i[1])
            
        for i,j in graph.items():
            graph[i] = sorted(j)
            
        n = len(tickets)

        def dfs(results,result):
            if len(results) == n+1:
                return True
            
            for i in range(len(graph[result])):
                now = graph[result].pop(0)
                results.append(now)
                if dfs(results,now):
                    return True
                graph[result].append(now)
                results.pop()
            return False
            
        results = ['JFK']
        dfs(results,'JFK')
        return results
1.比较容易理解的方式:

类似大部分基本深搜,每次对当前出发点的“剩余可用目的地”循环,优先去名字值小的
但无论以递归入参还是全局变量的方式,每次进递归需层数+1,选择的ticket要暂时标为已用,即当前form-to的剩余可用次数-1
结束条件是层数达到完全遍历,若未达到又无可用目的地,说明这条路走不通了,回溯时需还原层数、可用次数

2.更烧脑但更简洁的方式:

因题目强调了“假定所有机票至少存在一种合理的行程”,所以可利用深搜一定会有结果这一点,无需任何标记、判定,仅单纯对每层进行循环及扣除
也就是每次进递归,还是对当前“剩余可用目的地”循环,但选择名字值小的进入下层时直接扣除这张机票
这样任意循环若还能进行,说明还有机票没用;反之一定是“基于已经出现的终点,自身成为更早部分的终点”
这里有点绕,举例来说第一个结束循环的一定是唯一一个这样的机场:他作为机票的终点的总次数,比作为起点的总次数多1
也就是说JFK恰好是唯一相反的机场,而其它机场作为起点和终点的总次数一定相同
所以最早结束循环的递归,一定是入参为终点时,将其加入行程数组;第二个出现的,则是之前行程中,唯一可作为终点的
以此类推……最后行程数组反向,即为答案

import collections

class Solution:
    def findItinerary(self, tickets):
        paths = collections.defaultdict(list)
        for start, tar in tickets:
            paths[start].append(tar)
        for start in paths:
            paths[start].sort(reverse=True)
        s = []

        def search(start):
            while paths[start]:
                search(paths[start].pop())
            s.append(start)

        search("JFK")
        return s[::-1]

参考:https://leetcode-cn.com/problems/reconstruct-itinerary/comments/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
思路: 1. 先建立一个图,用邻接表表示。遍历tickets数组,以出发城市为键,以到达城市为值,将所有相同出发城市的到达城市加入到对应的键的值列表。 2. 对每个出发城市的到达城市列表进行排序,保证按字母顺序进行访问。 3. 从"JFK"出发,进行深度优先遍历。如果当前城市的到达城市列表不为空,则按顺序访问列表中的城市,并将访问过的城市从列表中删除。 4. 如果当前城市没有到达城市或者到达城市已经全部被访问过了,则将当前城市加入结果列表的头部。 5. 最后得到的结果列表,逆序输出即可得到答案。 代码实现如下: ```python from collections import defaultdict def findItinerary(tickets): # 用于保存图 graph = defaultdict(list) # 将tickets中的数据存入图 for ticket in tickets: src, dst = ticket graph[src].append(dst) # 按照字母顺序对到达城市进行排序 for src in graph: graph[src].sort() def dfs(city): # 当前城市的到达城市列表 destinations = graph[city] while destinations: # 递归遍历下一个城市 dfs(destinations.pop(0)) # 将当前城市加入结果列表 result.insert(0, city) # 结果列表 result = [] dfs("JFK") return result # 测试 tickets = [["MUC","LHR"],["JFK","MUC"],["SFO","SJC"],["LHR","SFO"]] print(findItinerary(tickets)) # 输出:['JFK', 'MUC', 'LHR', 'SFO', 'SJC'] ``` 复杂度分析: - 时间复杂度:建立图的过程需要遍历tickets数组,时间复杂度为O(n),其中n为数组的长度。遍历图的过程中,所有的边都会被访问一次,时间复杂度为O(m),其中m为图中的边数。因此,总的时间复杂度为O(n+m)。 - 空间复杂度:使用了一个字典来保存图,空间复杂度为O(m),其中m为图中的边数。递归调用的深度为图中的边数+1,空间复杂度为O(m+1)。最后返回的结果列表的空间复杂度为O(n),其中n为结果列表的长度。因此,总的空间复杂度为O(m+n)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值