题目地址:
给定一个二维数组,每一行是一个公交车路线的每一个车站的编号。再给定两个车站的编号S 和T,问从S到T至少坐多少个不同的公交车。
原文链接:blog.csdn.net/qq_46105170…
import java.util.*;
public class Solution {
public int numBusesToDestination(int[][] routes, int S, int T) {
if (routes == null || routes.length == 0) {
return -1;
}
// 如果出发点就等于终点,那么不需要乘车,返回0
if (S == T) {
return 0;
}
// key是车站编号,value是其能够到达的路线在routes数组中的下标
Map<Integer, List<Integer>> mapToRouteIdx = new HashMap<>();
for (int i = 0; i < routes.length; i++) {
for (int stop : routes[i]) {
mapToRouteIdx.computeIfAbsent(stop, k -> new ArrayList<>()).add(i);
}
}
// 开一个队列存储车站编号
Queue<Integer> queue = new LinkedList<>();
queue.offer(S);
// 开一个哈希表存储已经访问过的路线在routes中的下标
Set<Integer> visited = new HashSet<>();
// 记录乘过的路线的个数
int res = 0;
while (!queue.isEmpty()) {
res++;
// 要分层,所以先记录队列的size
int size = queue.size();
for (int i = 0; i < size; i++) {
// 取出当前车站,并遍历其能到达的路线
int cur = queue.poll();
for (int nextRouteIdx : mapToRouteIdx.get(cur)) {
// 如果这条路线访问过,就说明这个路线上车站都遍历过了,直接跳过不必重复遍历
if (visited.contains(nextRouteIdx)) {
continue;
}
// 否则将其标记一下
visited.add(nextRouteIdx);
// 遍历这条路线上的所有车站
for (int nextStop : routes[nextRouteIdx]) {
// 如果到达了终点,就返回步数
if (nextStop == T) {
return res;
}
queue.offer(nextStop);
}
}
}
}
return -1;
}
}