LeetCode 题解工作台

公交路线

给你一个数组 routes ,表示一系列公交线路,其中每个 routes[i] 表示一条公交线路,第 i 辆公交车将会在上面循环行驶。 例如,路线 routes[0] = [1, 5, 7] 表示第 0 辆公交车会一直按序列 1 -> 5 -> 7 -> 1 -> 5 -> 7 -> 1 -> ..…

category

3

题型

code_blocks

6

代码语言

hub

3

相关题

当前训练重点

困难 · 数组·哈希·扫描

bolt

答案摘要

我们首先判断 和 是否相同,如果相同则直接返回 。 然后我们使用一个哈希表 来构建站点到公交线路的映射。对于每一条公交线路,我们遍历其经过的所有站点,将每个站点映射到该公交线路,即 为经过站点 的所有公交线路。

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 数组·哈希·扫描 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

给你一个数组 routes ,表示一系列公交线路,其中每个 routes[i] 表示一条公交线路,第 i 辆公交车将会在上面循环行驶。

  • 例如,路线 routes[0] = [1, 5, 7] 表示第 0 辆公交车会一直按序列 1 -> 5 -> 7 -> 1 -> 5 -> 7 -> 1 -> ... 这样的车站路线行驶。

现在从 source 车站出发(初始时不在公交车上),要前往 target 车站。 期间仅可乘坐公交车。

求出 最少乘坐的公交车数量 。如果不可能到达终点车站,返回 -1

 

示例 1:

输入:routes = [[1,2,7],[3,6,7]], source = 1, target = 6
输出:2
解释:最优策略是先乘坐第一辆公交车到达车站 7 , 然后换乘第二辆公交车到车站 6 。 

示例 2:

输入:routes = [[7,12],[4,5,15],[6],[15,19],[9,12,13]], source = 15, target = 12
输出:-1

 

提示:

  • 1 <= routes.length <= 500.
  • 1 <= routes[i].length <= 105
  • routes[i] 中的所有值 互不相同
  • sum(routes[i].length) <= 105
  • 0 <= routes[i][j] < 106
  • 0 <= source, target < 106
lightbulb

解题思路

方法一:BFS

我们首先判断 source\textit{source}target\textit{target} 是否相同,如果相同则直接返回 00

然后我们使用一个哈希表 g\textit{g} 来构建站点到公交线路的映射。对于每一条公交线路,我们遍历其经过的所有站点,将每个站点映射到该公交线路,即 g[stop]\textit{g}[\textit{stop}] 为经过站点 stop\textit{stop} 的所有公交线路。

接着我们判断 source\textit{source}target\textit{target} 是否在站点映射中,如果不在则返回 1-1

我们使用一个队列 q\textit{q} 来进行广度优先搜索,队列中的每个元素为一个二元组 (stop,busCount)(\textit{stop}, \textit{busCount}),表示当前站点 stop\textit{stop} 和到达当前站点所需的公交次数 busCount\textit{busCount}

我们初始化一个集合 visBus\textit{visBus} 来记录已经访问过的公交线路,一个集合 visStop\textit{visStop} 来记录已经访问过的站点。然后我们将 source\textit{source} 加入到 visStop\textit{visStop} 中,并将 (source,0)(\textit{source}, 0) 加入到队列 q\textit{q} 中。

接下来我们开始广度优先搜索,当队列 q\textit{q} 不为空时,我们取出队列的第一个元素,即当前站点 stop\textit{stop} 和到达当前站点所需的公交次数 busCount\textit{busCount}

如果当前站点 stop\textit{stop} 是目标站点 target\textit{target},我们返回到达目标站点所需的公交次数 busCount\textit{busCount}

否则,我们遍历经过当前站点的所有公交线路,对于每一条公交线路,我们遍历该线路上的所有站点,如果某个站点 nextStop\textit{nextStop} 没有被访问过,则将其加入到 visStop\textit{visStop} 中,并将 (nextStop,busCount+1)(\textit{nextStop}, \textit{busCount} + 1) 加入到队列 q\textit{q} 中。

最后,如果无法到达目标站点,则返回 1-1

时间复杂度 O(L)O(L),空间复杂度 O(L)O(L),其中 LL 为所有公交线路上的站点总数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Solution:
    def numBusesToDestination(
        self, routes: List[List[int]], source: int, target: int
    ) -> int:
        if source == target:
            return 0
        # 使用 defaultdict 构建站点到公交线路的映射
        g = defaultdict(list)
        for i, route in enumerate(routes):
            for stop in route:
                g[stop].append(i)

        # 如果 source 或 target 不在站点映射中,返回 -1
        if source not in g or target not in g:
            return -1

        # 初始化队列和访问集合
        q = [(source, 0)]
        vis_bus = set()
        vis_stop = {source}

        # 开始广度优先搜索
        for stop, bus_count in q:
            # 如果当前站点是目标站点,返回所需的公交次数
            if stop == target:
                return bus_count

            # 遍历经过当前站点的所有公交线路
            for bus in g[stop]:
                if bus not in vis_bus:
                    vis_bus.add(bus)

                    # 遍历该线路上的所有站点
                    for next_stop in routes[bus]:
                        if next_stop not in vis_stop:
                            vis_stop.add(next_stop)
                            q.append((next_stop, bus_count + 1))
        return -1 # 如果无法到达目标站点,返回 -1
speed

复杂度分析

指标
时间O(M^2 * K + M * k * \log K)
空间O(M^2 + \log K)
psychology

面试官常问的追问

外企场景
  • question_mark

    They want you to count buses taken, so BFS levels should represent boarded routes rather than raw stop distance.

  • question_mark

    They expect you to notice that shared stops create an implicit graph between routes and stops.

  • question_mark

    They are testing whether you can replace repeated array scanning with a stop-to-route hash lookup.

warning

常见陷阱

外企场景
  • error

    Using BFS on stops without tracking bus layers can return the fewest stops traveled instead of the fewest buses taken.

  • error

    Reprocessing the same route from multiple shared stops causes massive duplicate scanning and time waste.

  • error

    Forgetting the source equals target shortcut leads to returning 1 instead of 0 on a trivial case.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Model routes as graph nodes and connect two routes if they share at least one stop, then BFS across routes.

  • arrow_right_alt

    Run bidirectional BFS from source-reachable routes and target-reachable routes when overlap is dense.

  • arrow_right_alt

    Return an actual transfer path by storing parent route or parent stop information during BFS.

help

常见问题

外企场景

公交路线题解:数组·哈希·扫描 | LeetCode #815 困难