一.题目
1926. 迷宫中离入口最近的出口 - 力扣(LeetCode)

二.思路讲解
2.1 本章讲什么
本章主要讲解在无权图 (即每一步移动的代价相同)中,如何用 BFS 求解最短路径问题。
-
因为 BFS 具有按层扩散的特性,从起点出发,第一次访问到某个格子时所经过的步数,就是到达该格子的最短距离。
-
因此,只要在 BFS 过程中记录当前层的层数,一旦遇到满足条件的出口(即边界上的空格子,且不是入口本身),就可以立即返回该层数,这就是最近出口的距离。
-
这种思想适用于所有移动代价为 1 的网格搜索问题。
2.2 思路讲解
对于本题,我们可以直接使用 BFS 从入口开始向外逐层探索:
-
将入口坐标入队,并标记已访问(防止走回头路)。
-
用变量
step记录当前层数(初始为 0)。 -
当队列不为空时,按层处理 :先记录当前层的大小
sz,然后循环sz次,依次取出队头格子。-
若当前格子位于迷宫边界(且不是入口),则返回
step(因为这是第一次到达边界,一定是最短路径)。 -
否则,向四个方向尝试移动,若邻居格子是空格子且未被访问,则将其入队并标记。
-
-
一层处理完后,
step++,继续下一层。 -
如果 BFS 结束后仍未找到出口,返回 -1。
三.代码演示
cpp
class Solution {
public:
int bx[4] = {0,0,-1,1};
int by[4] = {1,-1,0,0};
typedef pair<int,int>PII;
bool check[101][101];
int nearestExit(vector<vector<char>>& maze, vector<int>& entrance)
{
int step = 0;//步数
int row = maze.size(), col = maze[0].size();
int x = entrance[0],y = entrance[1];//获取起点
queue<PII>q;
q.push({x,y});
check[x][y] = true;
while(q.size())
{
step++;
int sz = q.size();
for(int i = 0;i < sz;i++)
{
auto [a,b] = q.front();
q.pop();
for(int k = 0;k < 4;k++)
{
int x = a + bx[k],y = b + by[k];
if(x >= 0 && y >= 0 && x < row && y < col && !check[x][y] && maze[x][y] == '.')
{
//如果下一个是出口
if(x == 0 || x == row - 1 || y == 0 || y == col - 1)
return step;
check[x][y] = true;
q.push({x,y});
}
}
}
}
return -1;//没找到出口
}
};
四.代码讲解
一、数据结构与初始化
-
bx[4]、by[4]:方向数组,表示上下左右四个方向的偏移量(顺序不限)。 -
check[101][101]:布尔数组,用于标记格子是否已被访问过,防止重复入队。 -
typedef pair<int,int> PII:简化坐标类型的书写。 -
step:整型变量,记录当前 BFS 的层数(即从起点出发已经移动的步数)。
二、主函数 nearestExit
-
获取迷宫尺寸和入口坐标 :
row = maze.size(); col = maze[0].size();x = entrance[0]; y = entrance[1]; -
初始化队列 :将入口坐标入队,并标记为已访问(
check[x][y] = true)。 -
BFS 层序遍历:
-
当队列非空时,进入循环,表示还有格子可以扩展。
-
step++:每开始新的一层,步数加 1,表示从起点出发已经走了step步。 -
int sz = q.size();:记录当前层的节点个数,用于逐层处理。
-
-
处理当前层所有节点 : 循环
sz次,依次取出队头坐标(a, b)。 对每个方向进行探索:-
计算新坐标
(x, y) = (a + bx[k], b + by[k])。 -
检查是否合法:在网格范围内、未被访问、且是空格子(
maze[x][y] == '.')。 -
若满足条件,则进一步判断:
-
如果新格子位于迷宫边界 (
x == 0 || x == row-1 || y == 0 || y == col-1),则说明找到了一个出口,由于 BFS 按层扩散,此时step即为最短步数,直接返回step。 -
否则,将新格子标记为已访问,并加入队列,供下一层探索。
-
-
-
循环结束 :若 BFS 结束后仍未返回,说明没有可到达的出口,返回
-1。
三、关键细节
-
BFS 的层序性质 :BFS 第一次访问到某个格子时,所用的步数就是最短距离。因此,只要在扩展过程中遇到边界格子,立即返回当前层数
step,保证结果是最小值。 -
步数递增时机 :
step++放在每层开始之前,表示进入下一层,这样第一次扩展到的出口对应的步数就是正确的。 -
入口不算出口:代码在扩展时只检查新格子是否为边界,且入口已经在初始时标记为已访问,因此不会将入口本身误判为出口。
五、流程图
