diff --git a/solution/0800-0899/0815.Bus Routes/README.md b/solution/0800-0899/0815.Bus Routes/README.md
index cc8396d967a20..ead566d7884d6 100644
--- a/solution/0800-0899/0815.Bus Routes/README.md
+++ b/solution/0800-0899/0815.Bus Routes/README.md
@@ -35,7 +35,7 @@ tags:
输入:routes = [[1,2,7],[3,6,7]], source = 1, target = 6
输出:2
-解释:最优策略是先乘坐第一辆公交车到达车站 7 , 然后换乘第二辆公交车到车站 6 。
+解释:最优策略是先乘坐第一辆公交车到达车站 7 , 然后换乘第二辆公交车到车站 6 。
示例 2:
@@ -64,17 +64,27 @@ tags:
-### 方法一:建图 + BFS
+### 方法一:BFS
-对于本题,我们可以将公交线路看成图中的节点,对于任意两条公交线路,如果它们有公共的公交站点,那么这两个公交线路之间就有一条边。
+我们首先判断 $\textit{source}$ 和 $\textit{target}$ 是否相同,如果相同则直接返回 $0$。
-我们用 $s[i]$ 表示公交线路 $i$ 上的所有公交站点,用哈希表 $d$ 存储每个公交站对应的所有公交线路。
+然后我们使用一个哈希表 $\textit{g}$ 来构建站点到公交线路的映射。对于每一条公交线路,我们遍历其经过的所有站点,将每个站点映射到该公交线路,即 $\textit{g}[\textit{stop}]$ 为经过站点 $\textit{stop}$ 的所有公交线路。
-接下来我们开始建图。遍历哈希表 $d$ 中每个公交站对应的公交线路,同个公交站的任意两条公交线路之间都有一条边,因此我们可以将这些公交线路看成图中的节点,将这些节点之间的边加入图 $g$ 中。
+接着我们判断 $\textit{source}$ 和 $\textit{target}$ 是否在站点映射中,如果不在则返回 $-1$。
-接下来,我们可以通过 BFS 求出从 $source$ 到 $target$ 的最短路径,即为最少乘坐的公交车数量。
+我们使用一个队列 $\textit{q}$ 来进行广度优先搜索,队列中的每个元素为一个二元组 $(\textit{stop}, \textit{busCount})$,表示当前站点 $\textit{stop}$ 和到达当前站点所需的公交次数 $\textit{busCount}$。
-时间复杂度 $O(n\times m + n^2)$。其中 $n$, $m$ 分别表示公交线路的数量和公交站的数量。
+我们初始化一个集合 $\textit{visBus}$ 来记录已经访问过的公交线路,一个集合 $\textit{visStop}$ 来记录已经访问过的站点。然后我们将 $\textit{source}$ 加入到 $\textit{visStop}$ 中,并将 $(\textit{source}, 0)$ 加入到队列 $\textit{q}$ 中。
+
+接下来我们开始广度优先搜索,当队列 $\textit{q}$ 不为空时,我们取出队列的第一个元素,即当前站点 $\textit{stop}$ 和到达当前站点所需的公交次数 $\textit{busCount}$。
+
+如果当前站点 $\textit{stop}$ 是目标站点 $\textit{target}$,我们返回到达目标站点所需的公交次数 $\textit{busCount}$。
+
+否则,我们遍历经过当前站点的所有公交线路,对于每一条公交线路,我们遍历该线路上的所有站点,如果某个站点 $\textit{nextStop}$ 没有被访问过,则将其加入到 $\textit{visStop}$ 中,并将 $(\textit{nextStop}, \textit{busCount} + 1)$ 加入到队列 $\textit{q}$ 中。
+
+最后,如果无法到达目标站点,则返回 $-1$。
+
+时间复杂度 $O(L)$,空间复杂度 $O(L)$,其中 $L$ 为所有公交线路上的站点总数。
@@ -87,38 +97,38 @@ class Solution:
) -> int:
if source == target:
return 0
-
- # 一条公交线路有哪些公交站
- s = [set(r) for r in routes]
-
- # 一个公交站在哪些公交线路有
- d = defaultdict(list)
- for i, r in enumerate(routes):
- for v in r:
- d[v].append(i)
-
+ # 使用 defaultdict 构建站点到公交线路的映射
g = defaultdict(list)
- for ids in d.values():
- m = len(ids)
- for i in range(m):
- for j in range(i + 1, m):
- a, b = ids[i], ids[j]
- g[a].append(b)
- g[b].append(a)
- q = deque(d[source])
- ans = 1
- vis = set(d[source])
- while q:
- for _ in range(len(q)):
- i = q.popleft()
- if target in s[i]:
- return ans
- for j in g[i]:
- if j not in vis:
- vis.add(j)
- q.append(j)
- ans += 1
- return -1
+ 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
```
#### Java
@@ -129,51 +139,51 @@ class Solution {
if (source == target) {
return 0;
}
- int n = routes.length;
- Set[] s = new Set[n];
- List[] g = new List[n];
- Arrays.setAll(s, k -> new HashSet<>());
- Arrays.setAll(g, k -> new ArrayList<>());
- Map> d = new HashMap<>();
- for (int i = 0; i < n; ++i) {
- for (int v : routes[i]) {
- s[i].add(v);
- d.computeIfAbsent(v, k -> new ArrayList<>()).add(i);
- }
- }
- for (var ids : d.values()) {
- int m = ids.size();
- for (int i = 0; i < m; ++i) {
- for (int j = i + 1; j < m; ++j) {
- int a = ids.get(i), b = ids.get(j);
- g[a].add(b);
- g[b].add(a);
- }
+
+ // 使用 HashMap 构建站点到公交线路的映射
+ Map> g = new HashMap<>();
+ for (int i = 0; i < routes.length; i++) {
+ for (int stop : routes[i]) {
+ g.computeIfAbsent(stop, k -> new ArrayList<>()).add(i);
}
}
- Deque q = new ArrayDeque<>();
- Set vis = new HashSet<>();
- int ans = 1;
- for (int v : d.get(source)) {
- q.offer(v);
- vis.add(v);
+
+ // 如果 source 或 target 不在站点映射中,返回 -1
+ if (!g.containsKey(source) || !g.containsKey(target)) {
+ return -1;
}
+
+ // 初始化队列和访问集合
+ Deque q = new ArrayDeque<>();
+ Set visBus = new HashSet<>();
+ Set visStop = new HashSet<>();
+ q.offer(new int[] {source, 0});
+ visStop.add(source);
+
+ // 开始广度优先搜索
while (!q.isEmpty()) {
- for (int k = q.size(); k > 0; --k) {
- int i = q.pollFirst();
- if (s[i].contains(target)) {
- return ans;
- }
- for (int j : g[i]) {
- if (!vis.contains(j)) {
- vis.add(j);
- q.offer(j);
+ int[] current = q.poll();
+ int stop = current[0], busCount = current[1];
+
+ // 如果当前站点是目标站点,返回所需的公交次数
+ if (stop == target) {
+ return busCount;
+ }
+
+ // 遍历经过当前站点的所有公交线路
+ for (int bus : g.get(stop)) {
+ if (visBus.add(bus)) {
+ // 遍历该线路上的所有站点
+ for (int nextStop : routes[bus]) {
+ if (visStop.add(nextStop)) {
+ q.offer(new int[] {nextStop, busCount + 1});
+ }
}
}
}
- ++ans;
}
- return -1;
+
+ return -1; // 如果无法到达目标站点,返回 -1
}
}
```
@@ -187,50 +197,53 @@ public:
if (source == target) {
return 0;
}
- int n = routes.size();
- vector> s(n);
- vector> g(n);
- unordered_map> d;
- for (int i = 0; i < n; ++i) {
- for (int v : routes[i]) {
- s[i].insert(v);
- d[v].push_back(i);
- }
- }
- for (auto& [_, ids] : d) {
- int m = ids.size();
- for (int i = 0; i < m; ++i) {
- for (int j = i + 1; j < m; ++j) {
- int a = ids[i], b = ids[j];
- g[a].push_back(b);
- g[b].push_back(a);
- }
+
+ // 使用 unordered_map 构建站点到公交线路的映射
+ unordered_map> g;
+ for (int i = 0; i < routes.size(); i++) {
+ for (int stop : routes[i]) {
+ g[stop].push_back(i);
}
}
- queue q;
- unordered_set vis;
- int ans = 1;
- for (int v : d[source]) {
- q.push(v);
- vis.insert(v);
+
+ // 如果 source 或 target 不在站点映射中,返回 -1
+ if (!g.contains(source) || !g.contains(target)) {
+ return -1;
}
+
+ // 初始化队列和访问集合
+ queue> q;
+ unordered_set visBus;
+ unordered_set visStop;
+ q.push({source, 0});
+ visStop.insert(source);
+
+ // 开始广度优先搜索
while (!q.empty()) {
- for (int k = q.size(); k; --k) {
- int i = q.front();
- q.pop();
- if (s[i].count(target)) {
- return ans;
- }
- for (int j : g[i]) {
- if (!vis.count(j)) {
- vis.insert(j);
- q.push(j);
+ auto [stop, busCount] = q.front();
+ q.pop();
+
+ // 如果当前站点是目标站点,返回所需的公交次数
+ if (stop == target) {
+ return busCount;
+ }
+
+ // 遍历经过当前站点的所有公交线路
+ for (int bus : g[stop]) {
+ if (!visBus.contains(bus)) {
+ visBus.insert(bus);
+ // 遍历该线路上的所有站点
+ for (int nextStop : routes[bus]) {
+ if (!visStop.contains(nextStop)) {
+ visStop.insert(nextStop);
+ q.push({nextStop, busCount + 1});
+ }
}
}
}
- ++ans;
}
- return -1;
+
+ return -1; // 如果无法到达目标站点,返回 -1
}
};
```
@@ -242,52 +255,109 @@ func numBusesToDestination(routes [][]int, source int, target int) int {
if source == target {
return 0
}
- n := len(routes)
- s := make([]map[int]bool, n)
- g := make([][]int, n)
- d := map[int][]int{}
- for i, r := range routes {
- for _, v := range r {
- if s[i] == nil {
- s[i] = make(map[int]bool)
- }
- s[i][v] = true
- d[v] = append(d[v], i)
- }
- }
- for _, ids := range d {
- m := len(ids)
- for i := 0; i < m; i++ {
- for j := i + 1; j < m; j++ {
- a, b := ids[i], ids[j]
- g[a] = append(g[a], b)
- g[b] = append(g[b], a)
- }
+
+ // 使用 map 构建站点到公交线路的映射
+ g := make(map[int][]int)
+ for i, route := range routes {
+ for _, stop := range route {
+ g[stop] = append(g[stop], i)
}
}
- q := d[source]
- vis := map[int]bool{}
- for _, v := range d[source] {
- vis[v] = true
+
+ // 如果 source 或 target 不在站点映射中,返回 -1
+ if g[source] == nil || g[target] == nil {
+ return -1
}
- ans := 1
- for len(q) > 0 {
- for k := len(q); k > 0; k-- {
- i := q[0]
- q = q[1:]
- if s[i][target] {
- return ans
- }
- for _, j := range g[i] {
- if !vis[j] {
- vis[j] = true
- q = append(q, j)
+
+ // 初始化队列和访问集合
+ q := list.New()
+ q.PushBack([2]int{source, 0})
+ visBus := make(map[int]bool)
+ visStop := make(map[int]bool)
+ visStop[source] = true
+
+ // 开始广度优先搜索
+ for q.Len() > 0 {
+ front := q.Front()
+ q.Remove(front)
+ stop, busCount := front.Value.([2]int)[0], front.Value.([2]int)[1]
+
+ // 如果当前站点是目标站点,返回所需的公交次数
+ if stop == target {
+ return busCount
+ }
+
+ // 遍历经过当前站点的所有公交线路
+ for _, bus := range g[stop] {
+ if !visBus[bus] {
+ visBus[bus] = true
+ // 遍历该线路上的所有站点
+ for _, nextStop := range routes[bus] {
+ if !visStop[nextStop] {
+ visStop[nextStop] = true
+ q.PushBack([2]int{nextStop, busCount + 1})
+ }
}
}
}
- ans++
}
- return -1
+
+ return -1 // 如果无法到达目标站点,返回
+}
+```
+
+#### TypeScript
+
+```ts
+function numBusesToDestination(routes: number[][], source: number, target: number): number {
+ if (source === target) {
+ return 0;
+ }
+
+ // 使用 Map 构建站点到公交线路的映射
+ const g: Map = new Map();
+ for (let i = 0; i < routes.length; i++) {
+ for (const stop of routes[i]) {
+ if (!g.has(stop)) {
+ g.set(stop, []);
+ }
+ g.get(stop)!.push(i);
+ }
+ }
+
+ // 如果 source 或 target 不在站点映射中,返回 -1
+ if (!g.has(source) || !g.has(target)) {
+ return -1;
+ }
+
+ // 初始化队列和访问集合
+ const q: [number, number][] = [[source, 0]];
+ const visBus: Set = new Set();
+ const visStop: Set = new Set([source]);
+
+ // 开始广度优先搜索
+ for (const [stop, busCount] of q) {
+ // 如果当前站点是目标站点,返回所需的公交次数
+ if (stop === target) {
+ return busCount;
+ }
+
+ // 遍历经过当前站点的所有公交线路
+ for (const bus of g.get(stop)!) {
+ if (!visBus.has(bus)) {
+ visBus.add(bus);
+ // 遍历该线路上的所有站点
+ for (const nextStop of routes[bus]) {
+ if (!visStop.has(nextStop)) {
+ visStop.add(nextStop);
+ q.push([nextStop, busCount + 1]);
+ }
+ }
+ }
+ }
+ }
+
+ return -1; // 如果无法到达目标站点,返回 -1
}
```
diff --git a/solution/0800-0899/0815.Bus Routes/README_EN.md b/solution/0800-0899/0815.Bus Routes/README_EN.md
index ebf250aa838af..88b81291ab647 100644
--- a/solution/0800-0899/0815.Bus Routes/README_EN.md
+++ b/solution/0800-0899/0815.Bus Routes/README_EN.md
@@ -64,7 +64,27 @@ tags:
-### Solution 1
+### Solution 1: BFS
+
+First, we check if $\textit{source}$ and $\textit{target}$ are the same. If they are, we directly return $0$.
+
+Next, we use a hash table $\textit{g}$ to build a mapping from stops to bus routes. For each bus route, we traverse all the stops it passes through and map each stop to that bus route, i.e., $\textit{g}[\textit{stop}]$ represents all bus routes passing through stop $\textit{stop}$.
+
+Then, we check if $\textit{source}$ and $\textit{target}$ are in the stop mapping. If they are not, we return $-1$.
+
+We use a queue $\textit{q}$ to perform a breadth-first search (BFS). Each element in the queue is a tuple $(\textit{stop}, \textit{busCount})$, representing the current stop $\textit{stop}$ and the number of buses taken to reach the current stop $\textit{busCount}$.
+
+We initialize a set $\textit{visBus}$ to record the bus routes that have been visited and a set $\textit{visStop}$ to record the stops that have been visited. Then, we add $\textit{source}$ to $\textit{visStop}$ and $(\textit{source}, 0)$ to the queue $\textit{q}$.
+
+Next, we start the BFS. While the queue $\textit{q}$ is not empty, we take out the first element from the queue, which is the current stop $\textit{stop}$ and the number of buses taken to reach the current stop $\textit{busCount}$.
+
+If the current stop $\textit{stop}$ is the target stop $\textit{target}$, we return the number of buses taken to reach the target stop $\textit{busCount}$.
+
+Otherwise, we traverse all bus routes passing through the current stop. For each bus route, we traverse all stops on that route. If a stop $\textit{nextStop}$ has not been visited, we add it to $\textit{visStop}$ and add $(\textit{nextStop}, \textit{busCount} + 1)$ to the queue $\textit{q}$.
+
+Finally, if we cannot reach the target stop, we return $-1$.
+
+The time complexity is $O(L)$, and the space complexity is $O(L)$, where $L$ is the total number of stops on all bus routes.
@@ -77,37 +97,25 @@ class Solution:
) -> int:
if source == target:
return 0
-
- # 一条公交线路有哪些公交站
- s = [set(r) for r in routes]
-
- # 一个公交站在哪些公交线路有
- d = defaultdict(list)
- for i, r in enumerate(routes):
- for v in r:
- d[v].append(i)
-
g = defaultdict(list)
- for ids in d.values():
- m = len(ids)
- for i in range(m):
- for j in range(i + 1, m):
- a, b = ids[i], ids[j]
- g[a].append(b)
- g[b].append(a)
- q = deque(d[source])
- ans = 1
- vis = set(d[source])
- while q:
- for _ in range(len(q)):
- i = q.popleft()
- if target in s[i]:
- return ans
- for j in g[i]:
- if j not in vis:
- vis.add(j)
- q.append(j)
- ans += 1
+ for i, route in enumerate(routes):
+ for stop in route:
+ g[stop].append(i)
+ 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
```
@@ -119,50 +127,42 @@ class Solution {
if (source == target) {
return 0;
}
- int n = routes.length;
- Set[] s = new Set[n];
- List[] g = new List[n];
- Arrays.setAll(s, k -> new HashSet<>());
- Arrays.setAll(g, k -> new ArrayList<>());
- Map> d = new HashMap<>();
- for (int i = 0; i < n; ++i) {
- for (int v : routes[i]) {
- s[i].add(v);
- d.computeIfAbsent(v, k -> new ArrayList<>()).add(i);
- }
- }
- for (var ids : d.values()) {
- int m = ids.size();
- for (int i = 0; i < m; ++i) {
- for (int j = i + 1; j < m; ++j) {
- int a = ids.get(i), b = ids.get(j);
- g[a].add(b);
- g[b].add(a);
- }
+
+ Map> g = new HashMap<>();
+ for (int i = 0; i < routes.length; i++) {
+ for (int stop : routes[i]) {
+ g.computeIfAbsent(stop, k -> new ArrayList<>()).add(i);
}
}
- Deque q = new ArrayDeque<>();
- Set vis = new HashSet<>();
- int ans = 1;
- for (int v : d.get(source)) {
- q.offer(v);
- vis.add(v);
+
+ if (!g.containsKey(source) || !g.containsKey(target)) {
+ return -1;
}
+
+ Deque q = new ArrayDeque<>();
+ Set visBus = new HashSet<>();
+ Set visStop = new HashSet<>();
+ q.offer(new int[] {source, 0});
+ visStop.add(source);
+
while (!q.isEmpty()) {
- for (int k = q.size(); k > 0; --k) {
- int i = q.pollFirst();
- if (s[i].contains(target)) {
- return ans;
- }
- for (int j : g[i]) {
- if (!vis.contains(j)) {
- vis.add(j);
- q.offer(j);
+ int[] current = q.poll();
+ int stop = current[0], busCount = current[1];
+
+ if (stop == target) {
+ return busCount;
+ }
+ for (int bus : g.get(stop)) {
+ if (visBus.add(bus)) {
+ for (int nextStop : routes[bus]) {
+ if (visStop.add(nextStop)) {
+ q.offer(new int[] {nextStop, busCount + 1});
+ }
}
}
}
- ++ans;
}
+
return -1;
}
}
@@ -177,49 +177,45 @@ public:
if (source == target) {
return 0;
}
- int n = routes.size();
- vector> s(n);
- vector> g(n);
- unordered_map> d;
- for (int i = 0; i < n; ++i) {
- for (int v : routes[i]) {
- s[i].insert(v);
- d[v].push_back(i);
- }
- }
- for (auto& [_, ids] : d) {
- int m = ids.size();
- for (int i = 0; i < m; ++i) {
- for (int j = i + 1; j < m; ++j) {
- int a = ids[i], b = ids[j];
- g[a].push_back(b);
- g[b].push_back(a);
- }
+
+ unordered_map> g;
+ for (int i = 0; i < routes.size(); i++) {
+ for (int stop : routes[i]) {
+ g[stop].push_back(i);
}
}
- queue q;
- unordered_set vis;
- int ans = 1;
- for (int v : d[source]) {
- q.push(v);
- vis.insert(v);
+
+ if (!g.contains(source) || !g.contains(target)) {
+ return -1;
}
+
+ queue> q;
+ unordered_set visBus;
+ unordered_set visStop;
+ q.push({source, 0});
+ visStop.insert(source);
+
while (!q.empty()) {
- for (int k = q.size(); k; --k) {
- int i = q.front();
- q.pop();
- if (s[i].count(target)) {
- return ans;
- }
- for (int j : g[i]) {
- if (!vis.count(j)) {
- vis.insert(j);
- q.push(j);
+ auto [stop, busCount] = q.front();
+ q.pop();
+
+ if (stop == target) {
+ return busCount;
+ }
+
+ for (int bus : g[stop]) {
+ if (!visBus.contains(bus)) {
+ for (int nextStop : routes[bus]) {
+ if (!visStop.contains(nextStop)) {
+ visBus.insert(bus);
+ visStop.insert(nextStop);
+ q.push({nextStop, busCount + 1});
+ }
}
}
}
- ++ans;
}
+
return -1;
}
};
@@ -232,55 +228,96 @@ func numBusesToDestination(routes [][]int, source int, target int) int {
if source == target {
return 0
}
- n := len(routes)
- s := make([]map[int]bool, n)
- g := make([][]int, n)
- d := map[int][]int{}
- for i, r := range routes {
- for _, v := range r {
- if s[i] == nil {
- s[i] = make(map[int]bool)
- }
- s[i][v] = true
- d[v] = append(d[v], i)
- }
- }
- for _, ids := range d {
- m := len(ids)
- for i := 0; i < m; i++ {
- for j := i + 1; j < m; j++ {
- a, b := ids[i], ids[j]
- g[a] = append(g[a], b)
- g[b] = append(g[b], a)
- }
+
+ g := make(map[int][]int)
+ for i, route := range routes {
+ for _, stop := range route {
+ g[stop] = append(g[stop], i)
}
}
- q := d[source]
- vis := map[int]bool{}
- for _, v := range d[source] {
- vis[v] = true
+
+ if g[source] == nil || g[target] == nil {
+ return -1
}
- ans := 1
- for len(q) > 0 {
- for k := len(q); k > 0; k-- {
- i := q[0]
- q = q[1:]
- if s[i][target] {
- return ans
- }
- for _, j := range g[i] {
- if !vis[j] {
- vis[j] = true
- q = append(q, j)
+
+ q := list.New()
+ q.PushBack([2]int{source, 0})
+ visBus := make(map[int]bool)
+ visStop := make(map[int]bool)
+ visStop[source] = true
+
+ for q.Len() > 0 {
+ front := q.Front()
+ q.Remove(front)
+ stop, busCount := front.Value.([2]int)[0], front.Value.([2]int)[1]
+
+ if stop == target {
+ return busCount
+ }
+
+ for _, bus := range g[stop] {
+ if !visBus[bus] {
+ visBus[bus] = true
+ for _, nextStop := range routes[bus] {
+ if !visStop[nextStop] {
+ visStop[nextStop] = true
+ q.PushBack([2]int{nextStop, busCount + 1})
+ }
}
}
}
- ans++
}
+
return -1
}
```
+#### TypeScript
+
+```ts
+function numBusesToDestination(routes: number[][], source: number, target: number): number {
+ if (source === target) {
+ return 0;
+ }
+
+ const g: Map = new Map();
+ for (let i = 0; i < routes.length; i++) {
+ for (const stop of routes[i]) {
+ if (!g.has(stop)) {
+ g.set(stop, []);
+ }
+ g.get(stop)!.push(i);
+ }
+ }
+
+ if (!g.has(source) || !g.has(target)) {
+ return -1;
+ }
+
+ const q: [number, number][] = [[source, 0]];
+ const visBus: Set = new Set();
+ const visStop: Set = new Set([source]);
+
+ for (const [stop, busCount] of q) {
+ if (stop === target) {
+ return busCount;
+ }
+ for (const bus of g.get(stop)!) {
+ if (!visBus.has(bus)) {
+ visBus.add(bus);
+ for (const nextStop of routes[bus]) {
+ if (!visStop.has(nextStop)) {
+ visStop.add(nextStop);
+ q.push([nextStop, busCount + 1]);
+ }
+ }
+ }
+ }
+ }
+ return -1;
+}
+```
+
#### C#
```cs
@@ -290,45 +327,39 @@ public class Solution {
return 0;
}
- Dictionary> stopToRoutes = new Dictionary>();
- List> routeToStops = new List>();
-
+ Dictionary> g = new Dictionary>();
for (int i = 0; i < routes.Length; i++) {
- routeToStops.Add(new HashSet());
foreach (int stop in routes[i]) {
- routeToStops[i].Add(stop);
- if (!stopToRoutes.ContainsKey(stop)) {
- stopToRoutes[stop] = new HashSet();
+ if (!g.ContainsKey(stop)) {
+ g[stop] = new List();
}
- stopToRoutes[stop].Add(i);
+ g[stop].Add(i);
}
}
- Queue queue = new Queue();
- HashSet visited = new HashSet();
- int ans = 0;
-
- foreach (int routeId in stopToRoutes[source]) {
- queue.Enqueue(routeId);
- visited.Add(routeId);
+ if (!g.ContainsKey(source) || !g.ContainsKey(target)) {
+ return -1;
}
- while (queue.Count > 0) {
- int count = queue.Count;
- ans++;
-
- for (int i = 0; i < count; i++) {
- int routeId = queue.Dequeue();
-
- foreach (int stop in routeToStops[routeId]) {
- if (stop == target) {
- return ans;
- }
-
- foreach (int nextRoute in stopToRoutes[stop]) {
- if (!visited.Contains(nextRoute)) {
- visited.Add(nextRoute);
- queue.Enqueue(nextRoute);
+ Queue q = new Queue();
+ HashSet visBus = new HashSet();
+ HashSet visStop = new HashSet();
+ q.Enqueue(new int[]{source, 0});
+ visStop.Add(source);
+
+ while (q.Count > 0) {
+ int[] current = q.Dequeue();
+ int stop = current[0], busCount = current[1];
+ if (stop == target) {
+ return busCount;
+ }
+ foreach (int bus in g[stop]) {
+ if (!visBus.Contains(bus)) {
+ foreach (int nextStop in routes[bus]) {
+ if (!visStop.Contains(nextStop)) {
+ visBus.Add(bus);
+ visStop.Add(nextStop);
+ q.Enqueue(new int[]{nextStop, busCount + 1});
}
}
}
diff --git a/solution/0800-0899/0815.Bus Routes/Solution.cpp b/solution/0800-0899/0815.Bus Routes/Solution.cpp
index 0d1355d77a7d7..87ff1a435d860 100644
--- a/solution/0800-0899/0815.Bus Routes/Solution.cpp
+++ b/solution/0800-0899/0815.Bus Routes/Solution.cpp
@@ -4,49 +4,45 @@ class Solution {
if (source == target) {
return 0;
}
- int n = routes.size();
- vector> s(n);
- vector> g(n);
- unordered_map> d;
- for (int i = 0; i < n; ++i) {
- for (int v : routes[i]) {
- s[i].insert(v);
- d[v].push_back(i);
+
+ unordered_map> g;
+ for (int i = 0; i < routes.size(); i++) {
+ for (int stop : routes[i]) {
+ g[stop].push_back(i);
}
}
- for (auto& [_, ids] : d) {
- int m = ids.size();
- for (int i = 0; i < m; ++i) {
- for (int j = i + 1; j < m; ++j) {
- int a = ids[i], b = ids[j];
- g[a].push_back(b);
- g[b].push_back(a);
- }
- }
- }
- queue q;
- unordered_set vis;
- int ans = 1;
- for (int v : d[source]) {
- q.push(v);
- vis.insert(v);
+
+ if (!g.contains(source) || !g.contains(target)) {
+ return -1;
}
+
+ queue> q;
+ unordered_set visBus;
+ unordered_set visStop;
+ q.push({source, 0});
+ visStop.insert(source);
+
while (!q.empty()) {
- for (int k = q.size(); k; --k) {
- int i = q.front();
- q.pop();
- if (s[i].count(target)) {
- return ans;
- }
- for (int j : g[i]) {
- if (!vis.count(j)) {
- vis.insert(j);
- q.push(j);
+ auto [stop, busCount] = q.front();
+ q.pop();
+
+ if (stop == target) {
+ return busCount;
+ }
+
+ for (int bus : g[stop]) {
+ if (!visBus.contains(bus)) {
+ for (int nextStop : routes[bus]) {
+ if (!visStop.contains(nextStop)) {
+ visBus.insert(bus);
+ visStop.insert(nextStop);
+ q.push({nextStop, busCount + 1});
+ }
}
}
}
- ++ans;
}
+
return -1;
}
-};
\ No newline at end of file
+};
diff --git a/solution/0800-0899/0815.Bus Routes/Solution.cs b/solution/0800-0899/0815.Bus Routes/Solution.cs
index 0baab5a907de9..67b90242a10e8 100644
--- a/solution/0800-0899/0815.Bus Routes/Solution.cs
+++ b/solution/0800-0899/0815.Bus Routes/Solution.cs
@@ -4,45 +4,39 @@ public int NumBusesToDestination(int[][] routes, int source, int target) {
return 0;
}
- Dictionary> stopToRoutes = new Dictionary>();
- List> routeToStops = new List>();
-
+ Dictionary> g = new Dictionary>();
for (int i = 0; i < routes.Length; i++) {
- routeToStops.Add(new HashSet());
foreach (int stop in routes[i]) {
- routeToStops[i].Add(stop);
- if (!stopToRoutes.ContainsKey(stop)) {
- stopToRoutes[stop] = new HashSet();
+ if (!g.ContainsKey(stop)) {
+ g[stop] = new List();
}
- stopToRoutes[stop].Add(i);
+ g[stop].Add(i);
}
}
- Queue queue = new Queue();
- HashSet visited = new HashSet();
- int ans = 0;
-
- foreach (int routeId in stopToRoutes[source]) {
- queue.Enqueue(routeId);
- visited.Add(routeId);
+ if (!g.ContainsKey(source) || !g.ContainsKey(target)) {
+ return -1;
}
- while (queue.Count > 0) {
- int count = queue.Count;
- ans++;
-
- for (int i = 0; i < count; i++) {
- int routeId = queue.Dequeue();
-
- foreach (int stop in routeToStops[routeId]) {
- if (stop == target) {
- return ans;
- }
-
- foreach (int nextRoute in stopToRoutes[stop]) {
- if (!visited.Contains(nextRoute)) {
- visited.Add(nextRoute);
- queue.Enqueue(nextRoute);
+ Queue q = new Queue();
+ HashSet visBus = new HashSet();
+ HashSet visStop = new HashSet();
+ q.Enqueue(new int[]{source, 0});
+ visStop.Add(source);
+
+ while (q.Count > 0) {
+ int[] current = q.Dequeue();
+ int stop = current[0], busCount = current[1];
+ if (stop == target) {
+ return busCount;
+ }
+ foreach (int bus in g[stop]) {
+ if (!visBus.Contains(bus)) {
+ foreach (int nextStop in routes[bus]) {
+ if (!visStop.Contains(nextStop)) {
+ visBus.Add(bus);
+ visStop.Add(nextStop);
+ q.Enqueue(new int[]{nextStop, busCount + 1});
}
}
}
diff --git a/solution/0800-0899/0815.Bus Routes/Solution.go b/solution/0800-0899/0815.Bus Routes/Solution.go
index 9f4ea10feb032..3c41190122280 100644
--- a/solution/0800-0899/0815.Bus Routes/Solution.go
+++ b/solution/0800-0899/0815.Bus Routes/Solution.go
@@ -2,50 +2,45 @@ func numBusesToDestination(routes [][]int, source int, target int) int {
if source == target {
return 0
}
- n := len(routes)
- s := make([]map[int]bool, n)
- g := make([][]int, n)
- d := map[int][]int{}
- for i, r := range routes {
- for _, v := range r {
- if s[i] == nil {
- s[i] = make(map[int]bool)
- }
- s[i][v] = true
- d[v] = append(d[v], i)
- }
- }
- for _, ids := range d {
- m := len(ids)
- for i := 0; i < m; i++ {
- for j := i + 1; j < m; j++ {
- a, b := ids[i], ids[j]
- g[a] = append(g[a], b)
- g[b] = append(g[b], a)
- }
+
+ g := make(map[int][]int)
+ for i, route := range routes {
+ for _, stop := range route {
+ g[stop] = append(g[stop], i)
}
}
- q := d[source]
- vis := map[int]bool{}
- for _, v := range d[source] {
- vis[v] = true
+
+ if g[source] == nil || g[target] == nil {
+ return -1
}
- ans := 1
- for len(q) > 0 {
- for k := len(q); k > 0; k-- {
- i := q[0]
- q = q[1:]
- if s[i][target] {
- return ans
- }
- for _, j := range g[i] {
- if !vis[j] {
- vis[j] = true
- q = append(q, j)
+
+ q := list.New()
+ q.PushBack([2]int{source, 0})
+ visBus := make(map[int]bool)
+ visStop := make(map[int]bool)
+ visStop[source] = true
+
+ for q.Len() > 0 {
+ front := q.Front()
+ q.Remove(front)
+ stop, busCount := front.Value.([2]int)[0], front.Value.([2]int)[1]
+
+ if stop == target {
+ return busCount
+ }
+
+ for _, bus := range g[stop] {
+ if !visBus[bus] {
+ visBus[bus] = true
+ for _, nextStop := range routes[bus] {
+ if !visStop[nextStop] {
+ visStop[nextStop] = true
+ q.PushBack([2]int{nextStop, busCount + 1})
+ }
}
}
}
- ans++
}
+
return -1
-}
\ No newline at end of file
+}
diff --git a/solution/0800-0899/0815.Bus Routes/Solution.java b/solution/0800-0899/0815.Bus Routes/Solution.java
index 6dedae230274e..3e59dbde501ad 100644
--- a/solution/0800-0899/0815.Bus Routes/Solution.java
+++ b/solution/0800-0899/0815.Bus Routes/Solution.java
@@ -3,50 +3,42 @@ public int numBusesToDestination(int[][] routes, int source, int target) {
if (source == target) {
return 0;
}
- int n = routes.length;
- Set[] s = new Set[n];
- List[] g = new List[n];
- Arrays.setAll(s, k -> new HashSet<>());
- Arrays.setAll(g, k -> new ArrayList<>());
- Map> d = new HashMap<>();
- for (int i = 0; i < n; ++i) {
- for (int v : routes[i]) {
- s[i].add(v);
- d.computeIfAbsent(v, k -> new ArrayList<>()).add(i);
+
+ Map> g = new HashMap<>();
+ for (int i = 0; i < routes.length; i++) {
+ for (int stop : routes[i]) {
+ g.computeIfAbsent(stop, k -> new ArrayList<>()).add(i);
}
}
- for (var ids : d.values()) {
- int m = ids.size();
- for (int i = 0; i < m; ++i) {
- for (int j = i + 1; j < m; ++j) {
- int a = ids.get(i), b = ids.get(j);
- g[a].add(b);
- g[b].add(a);
- }
- }
- }
- Deque q = new ArrayDeque<>();
- Set vis = new HashSet<>();
- int ans = 1;
- for (int v : d.get(source)) {
- q.offer(v);
- vis.add(v);
+
+ if (!g.containsKey(source) || !g.containsKey(target)) {
+ return -1;
}
+
+ Deque q = new ArrayDeque<>();
+ Set visBus = new HashSet<>();
+ Set visStop = new HashSet<>();
+ q.offer(new int[] {source, 0});
+ visStop.add(source);
+
while (!q.isEmpty()) {
- for (int k = q.size(); k > 0; --k) {
- int i = q.pollFirst();
- if (s[i].contains(target)) {
- return ans;
- }
- for (int j : g[i]) {
- if (!vis.contains(j)) {
- vis.add(j);
- q.offer(j);
+ int[] current = q.poll();
+ int stop = current[0], busCount = current[1];
+
+ if (stop == target) {
+ return busCount;
+ }
+ for (int bus : g.get(stop)) {
+ if (visBus.add(bus)) {
+ for (int nextStop : routes[bus]) {
+ if (visStop.add(nextStop)) {
+ q.offer(new int[] {nextStop, busCount + 1});
+ }
}
}
}
- ++ans;
}
+
return -1;
}
-}
\ No newline at end of file
+}
diff --git a/solution/0800-0899/0815.Bus Routes/Solution.py b/solution/0800-0899/0815.Bus Routes/Solution.py
index 3dfb07db8d911..62d94ce5ac17f 100644
--- a/solution/0800-0899/0815.Bus Routes/Solution.py
+++ b/solution/0800-0899/0815.Bus Routes/Solution.py
@@ -4,35 +4,23 @@ def numBusesToDestination(
) -> int:
if source == target:
return 0
-
- # 一条公交线路有哪些公交站
- s = [set(r) for r in routes]
-
- # 一个公交站在哪些公交线路有
- d = defaultdict(list)
- for i, r in enumerate(routes):
- for v in r:
- d[v].append(i)
-
g = defaultdict(list)
- for ids in d.values():
- m = len(ids)
- for i in range(m):
- for j in range(i + 1, m):
- a, b = ids[i], ids[j]
- g[a].append(b)
- g[b].append(a)
- q = deque(d[source])
- ans = 1
- vis = set(d[source])
- while q:
- for _ in range(len(q)):
- i = q.popleft()
- if target in s[i]:
- return ans
- for j in g[i]:
- if j not in vis:
- vis.add(j)
- q.append(j)
- ans += 1
+ for i, route in enumerate(routes):
+ for stop in route:
+ g[stop].append(i)
+ 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
diff --git a/solution/0800-0899/0815.Bus Routes/Solution.ts b/solution/0800-0899/0815.Bus Routes/Solution.ts
new file mode 100644
index 0000000000000..3895be1e11362
--- /dev/null
+++ b/solution/0800-0899/0815.Bus Routes/Solution.ts
@@ -0,0 +1,41 @@
+function numBusesToDestination(routes: number[][], source: number, target: number): number {
+ if (source === target) {
+ return 0;
+ }
+
+ const g: Map = new Map();
+ for (let i = 0; i < routes.length; i++) {
+ for (const stop of routes[i]) {
+ if (!g.has(stop)) {
+ g.set(stop, []);
+ }
+ g.get(stop)!.push(i);
+ }
+ }
+
+ if (!g.has(source) || !g.has(target)) {
+ return -1;
+ }
+
+ const q: [number, number][] = [[source, 0]];
+ const visBus: Set = new Set();
+ const visStop: Set = new Set([source]);
+
+ for (const [stop, busCount] of q) {
+ if (stop === target) {
+ return busCount;
+ }
+ for (const bus of g.get(stop)!) {
+ if (!visBus.has(bus)) {
+ visBus.add(bus);
+ for (const nextStop of routes[bus]) {
+ if (!visStop.has(nextStop)) {
+ visStop.add(nextStop);
+ q.push([nextStop, busCount + 1]);
+ }
+ }
+ }
+ }
+ }
+ return -1;
+}