
华为OD机试 新系统 题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试(JAVA)真题》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天优快云在线答疑。
一、题目内容
小菊听说在一个神秘的城堡里藏着宝藏,她决定去寻宝。城堡由 n n n 个房间组成,某些房间之间有通道相连。小菊从房间 s s s 出发,想要到达藏有宝藏的房间 t t t。
给定房间数量
n
n
n、通道列表 edges、起点
s
s
s 和终点
t
t
t,求小菊从起点到终点经过通道最短的路径长度(通道长度相同且长度为 1,例如:房间 1 → 房间 2 → 房间 3,经过 2 条通道,长度 = 2)。
如果起点终点相同,返回 0;如果房间无法到达,返回 −1。
二、输入描述
顶点数量 n n n:
- 1 ≤ n ≤ 10000 1 \le n \le 10000 1≤n≤10000
- 顶点编号:从 1 到 n n n(连续编号)
- 单顶点情况: n = 1 n = 1 n=1 时,起点终点相同,路径长度为 0
边数量和边参数 edges:
- 边数量 m m m: 0 ≤ m ≤ min ( n ( n − 1 ) 2 , 100000 ) 0 \le m \le \min\left(\frac{n(n-1)}{2},100000\right) 0≤m≤min(2n(n−1),100000)
- 每条边 [ u , v ] [u,v] [u,v]:
- 1 ≤ u , v ≤ n 1 \le u,v \le n 1≤u,v≤n(顶点编号合法)
- u u u 和 v v v 可以相等(允许自环,但不影响路径长度)
- 边是无向的: ( u , v ) (u,v) (u,v) 表示房间 u u u 和房间 v v v 之间有一条双向通道
- 允许重边:多条边连接同一对顶点(不影响最短路径)
起点和终点参数:
- 起点 s s s: 1 ≤ s ≤ n 1 \le s \le n 1≤s≤n
- 终点 t t t: 1 ≤ t ≤ n 1 \le t \le n 1≤t≤n
三、输出描述
返回从起点 s s s 到终点 t t t 的最短路径长度(经过的通道数)。若 s = t s = t s=t 则返回 0;若不可达则返回 −1。
四、测试用例
测试用例1:
1、输入
4
1,2 2,3 3,4 1,3
1 4
2、输出
2
3、说明
最短路径为 1 → 3 → 4,经过 2 条通道;而 1 → 2 → 3 → 4 需要 3 条,因此输出 2。
测试用例2:
1、输入
4
1,2 2,1 3,4 4,3
1 3
2、输出
-1
3、说明
房间 1 和 2 属于一个连通分量,房间 3 和 4 属于另一个连通分量。即使存在反向重复边,也无法从 1 到达 3。
五、解题思路
1. 问题分析
城堡中的每个房间可以看作图中的一个顶点,每条通道可以看作连接两个顶点的无向边。
由于每条通道的长度均为 1,因此本题本质上是求无权无向图中,从起点 s 到终点 t 的最短路径长度。
如果起点和终点相同,直接返回 0;如果起点无法到达终点,则返回 -1。
2. 数据结构选择
使用邻接表存储无向图,使用队列辅助广度优先搜索,使用距离数组 dist 记录最短路径长度。
- 邻接表:存储每个房间直接连接的其他房间。
- 队列:保证 BFS 按距离从近到远搜索。
- 距离数组:初始化为 -1,既表示未访问状态,也记录最短距离。
相比邻接矩阵,邻接表只需 O(n+m) 的空间,更适合 n 最大为 10000、m 最大为 100000 的数据规模。
3. 算法步骤
- 读取房间数量 n、边列表、起点 s 和终点 t。
- 如果 s == t,直接输出 0。
- 根据边列表构建无向图,每条有效边需要双向添加。
- 初始化距离数组为 -1,设置 dist[s]=0,并将 s 加入队列。
- 从队列取出当前房间,遍历其相邻房间。
- 如果相邻房间尚未访问,则将其距离设置为当前距离加 1,并加入队列。
- 如果首次发现终点 t,立即返回对应距离。
- 如果队列为空仍未找到终点,输出 -1。
4. 正确性分析
BFS 按路径长度逐层扩展。由于所有边的长度均为 1,首次访问一个房间时,所经过的通道数一定最少。
因此,首次到达终点时得到的距离就是最短路径长度。
自环不影响最短路径,可以忽略;重边通过距离数组避免重复访问,不影响结果。
5. 复杂度分析
- 时间复杂度:O(n+m),每个顶点最多入队一次,每条边最多检查两次。
- 空间复杂度:O(n+m),主要用于邻接表、距离数组及 BFS 队列。
该算法能够高效处理题目规定的数据规模。
六、Java算法源码
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Queue;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class OdTest {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 输入固定为三行:房间数量、边列表、起点和终点。
// 第二行可能为空,表示没有通道,因此不能用 next() 读取边列表。
int n = Integer.parseInt(scanner.nextLine().trim());
String edgesLine = scanner.nextLine();
int s = scanner.nextInt();
int t = scanner.nextInt();
if (s == t) {
System.out.println(0);
scanner.close();
return;
}
// 使用邻接表存储无向图,空间复杂度 O(n + m)。
// 正则兼容 1,2、1, 2 以及边与边之间的多个空格。
List<List<Integer>> graph = new ArrayList<>(n + 1);
for (int i = 0; i <= n; i++) {
graph.add(new ArrayList<>());
}
Matcher matcher = Pattern
.compile("(\\d+)\\s*,\\s*(\\d+)")
.matcher(edgesLine);
while (matcher.find()) {
int u = Integer.parseInt(matcher.group(1));
int v = Integer.parseInt(matcher.group(2));
// 自环不会缩短到其他房间的路径,直接忽略。
if (u != v) {
graph.get(u).add(v);
graph.get(v).add(u);
}
}
// BFS 按经过通道的数量逐层扩展,
// 首次到达终点即得到最短路径。
// dist 同时记录距离和是否访问:
// -1 表示尚未访问。
int[] dist = new int[n + 1];
Arrays.fill(dist, -1);
Queue<Integer> queue = new ArrayDeque<>();
dist[s] = 0;
queue.offer(s);
while (!queue.isEmpty()) {
int u = queue.poll();
for (int v : graph.get(u)) {
if (dist[v] != -1) {
// 防止无向边反复回走,
// 重边也不会造成重复入队。
continue;
}
dist[v] = dist[u] + 1;
if (v == t) {
System.out.println(dist[v]);
scanner.close();
return;
}
queue.offer(v);
}
}
// BFS 结束仍未找到终点,说明不可达。
System.out.println(-1);
scanner.close();
}
}
七、效果展示
1、输入
6
1,2 2,3 1,4 4,5 5,6 3,6 2,2
1 6
2、输出
3
3、说明
可以沿着 1 → 2 → 3 → 6 或 1 → 4 → 5 → 6 到达终点,两条路径长度均为 3。房间 2 的自环不影响结果。

🏆下一篇:华为OD机试 - 简易内存池 - 逻辑分析(Java 新系统 200分)
🏆本专栏收录于《华为OD机试(JAVA)真题》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天优快云在线答疑。

本题为华为OD机试真题,要求在无权无向图中求起点到终点的最短路径长度(边数)。采用广度优先搜索(BFS)算法,利用邻接表建图、队列逐层扩展、距离数组记录最短距离。时间复杂度O(n+m),空间复杂度O(n+m),适用于n≤10000、m≤100000的大规模图。支持自环与重边,不可达时返回-1。
966

被折叠的 条评论
为什么被折叠?



