思路分析
- BFS 核心逻辑:BFS 按「层」遍历,每一层对应「移动一步」,首次到达迷宫边界的空单元格时,当前层数就是最短距离(无需遍历所有路径)。
- 网格遍历关键:
用队列存储每一层的单元格坐标(记录[x, y, 步数]);
用访问标记(直接修改原网格 / 单独二维数组)避免重复访问(防止绕圈);
边界判断:单元格的x=0/x=m-1/y=0/y=n-1 即为迷宫边界。 - 步骤拆解:
初始化:入口入队,标记为已访问(避免回头),初始步数为0;
循环遍历队列:取出当前层所有单元格,遍历上下左右四个方向;
合法性判断:新坐标不越界、不是墙、未访问;
出口判断:若新坐标是边界空单元格,直接返回「当前步数 + 1」;
入队处理:非出口则标记为已访问,入队并步数 + 1;
无出口:队列遍历完仍未找到,返回-1。
代码实现
java
public int nearestExit(char[][] maze, int[] entrace){
// 获取迷宫大小/维度
int m = maze.length;
int n = maze[0].length;
// 定义方向数组
int[][] dirs = {
{-1, 0},
{1, 0},
{0, -1},
{0, 1}
};
// 定义队列
Queue<int[]> queue = new LinkedList<>();
// 初始化队列
int x = entrace[0];
int y = entrace[1];
queue.offer(new int[]{x, y, 0});
// 标记入口为已访问
maze[x][y] = '+';
// 遍历队列
while(!queue.isEmpty()){
// 得到队首元素
int[] cur = queue.poll();
int curx = cur[0];
int cury = cur[1];
int step = cur[2];
// 遍历方向
for (int[] dir : dirs) {
// 计算下一个位置
int nextx = curx + dir[0];
int nexty = cury + dir[1];
// 是否未超出边界
if (nextx >= 0 && nextx < m && nexty >= 0 && nexty < n) {
// 是否为出口
if (maze[nextx][nexty] == '.') {
// 如果是出口,就返回
if (nextx == 0 || nextx == m-1 || nexty == 0 || nexty == n-1) {
return step + 1;
}
// 标记为已访问
maze[nextx][nexty] = '+';
// 加入队列
queue.offer(new int[]{nextx, nexty, step+1});
}
}
}
}
return -1;
}
复杂度分析
- 时间复杂度:O(m×n),每个单元格最多入队 / 出队一次,m、n 为迷宫的行列数;
- 空间复杂度:O(m×n),最坏情况队列存储所有单元格(如迷宫全是空单元格),方向数组和临时变量为常数空间O(1)。