公交路线
难度:
标签:
题目描述
代码结果
运行时间: 116 ms, 内存: 40.6 MB
/*
* 思路:
* 1. 使用广度优先搜索(BFS)来寻找最短路径。
* 2. 创建一个映射,将每个车站映射到经过该车站的公交车集合。
* 3. 使用队列进行BFS,记录访问过的车站和公交车。
* 4. 每次从队列中取出一个车站,遍历经过该车站的所有公交车。
* 5. 对于每辆公交车,遍历其所有经过的车站,如果是目标车站,返回当前乘坐公交车的数量。
* 6. 如果所有可能性都遍历完还没找到目标车站,返回-1。
*/
import java.util.*;
import java.util.stream.Collectors;
public class Solution {
public int numBusesToDestination(int[][] routes, int source, int target) {
if (source == target) return 0;
Map<Integer, Set<Integer>> stationToBuses = Arrays.stream(routes)
.flatMapToInt(Arrays::stream)
.boxed()
.distinct()
.collect(Collectors.toMap(
station -> station,
station -> new HashSet<>(),
(a, b) -> a,
HashMap::new
));
for (int bus = 0; bus < routes.length; bus++) {
for (int station : routes[bus]) {
stationToBuses.get(station).add(bus);
}
}
Queue<int[]> queue = new LinkedList<>();
Set<Integer> visitedStations = new HashSet<>();
Set<Integer> visitedBuses = new HashSet<>();
queue.offer(new int[]{source, 0});
visitedStations.add(source);
while (!queue.isEmpty()) {
int[] current = queue.poll();
int station = current[0];
int buses = current[1];
for (int bus : stationToBuses.getOrDefault(station, new HashSet<>())) {
if (visitedBuses.contains(bus)) continue;
visitedBuses.add(bus);
for (int nextStation : routes[bus]) {
if (nextStation == target) return buses + 1;
if (visitedStations.contains(nextStation)) continue;
visitedStations.add(nextStation);
queue.offer(new int[]{nextStation, buses + 1});
}
}
}
return -1;
}
}
解释
方法:
该题解采用了宽度优先搜索(BFS)的策略。首先,使用一个字典 transpose 将站点和公交路线进行映射,键为站点,值为经过该站点的所有公交路线的索引。接着,从源站点出发,使用队列进行层序遍历,每一层代表乘坐一次公交车。遍历过程中,记录已访问的站点和已乘坐的公交路线,以避免重复访问。当到达目标站点时,返回当前的乘坐次数。
时间复杂度:
O(S * R)
空间复杂度:
O(S * R)
代码细节讲解
🦆
在算法中,为什么选择宽度优先搜索(BFS)而不是深度优先搜索(DFS)来解决这个问题?
▷🦆
构建`transpose`字典时,为什么需要将站点作为键,而公交路线索引作为值?这样的数据结构设计有什么特别的好处?
▷🦆
在BFS中使用队列时,每次从队列中取出元素时都进行了什么操作?这对找到最少乘坐次数的目标有何影响?
▷🦆
算法中如何处理循环路线,即公交车线路中包含重复站点的情况?
▷