一.题目

二.思路讲解
2.1 思路讲解
本题与 DFS 解法思路一致,只是将深度优先搜索 替换为广度优先搜索。
-
从矩阵的边界 出发,将所有与边界相连的
'O'标记为临时字符(如'.'),因为它们不会被包围。 -
使用队列 进行 BFS:将边界上的
'O'入队,并标记;然后不断取出队头,向四个方向扩散,遇到未访问的'O'则入队并标记。 -
遍历结束后,矩阵中剩下的
'O'就是被完全包围的区域,将其改为'X';同时将临时标记的'.'恢复为'O'。
三.代码演示
cpp
class Solution {
public:
int row,col;
int check[201][201];
int bx[4] = {1,-1,0,0};
int by[4] = {0,0,-1,1};
typedef pair<int,int> PII;//坐标
void solve(vector<vector<char>>& board)
{
row = board.size(),col = board[0].size();
//处理上边界
for(int j = 0;j < col;j++)
{
if(check[0][j] != true && board[0][j] == 'O') bfs(board,0,j);
}
//处理下边界
for(int j = 0;j < col;j++)
{
if(check[row - 1][j] != true && board[row - 1][j] == 'O') bfs(board,row - 1,j);
}
//左边界
for(int i = 0;i < row;i++)
{
if(check[i][0] != true && board[i][0] == 'O') bfs(board,i,0);
}
//右边界
for(int i = 0;i < row;i++)
{
if(check[i][col - 1] != true && board[i][col - 1] == 'O') bfs(board,i,col - 1);
}
//遍历矩阵把.变成O,O变成X即可
for(int i = 0;i < row;i++)
{
for(int j = 0;j < col;j++)
{
if(board[i][j] == '.') board[i][j] = 'O';
else if(board[i][j] == 'O') board[i][j] = 'X';
}
}
}
void bfs(vector<vector<char>>& board,int i,int j)
{
queue<PII>q;
q.push({i,j});
//处理一开始的
board[i][j] = '.';
check[i][j] = true;
while(q.size())
{
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] && board[x][y] == 'O')
{
board[x][y] = '.';
check[x][y] = true;
q.push({x,y});
}
}
}
}
};
四.代码讲解
一、全局变量与数据结构
-
row、col:成员变量,存储矩阵的行数和列数。 -
check[201][201]:整型数组,用于标记格子是否已被访问。注意:使用前必须清零,否则残留值会导致判断错误。 -
bx[4]、by[4]:方向数组,表示上下左右四个方向的偏移量(顺序不限)。 -
typedef pair<int,int> PII:简化坐标类型的书写。
二、主函数 solve
-
获取矩阵尺寸 :
row = board.size(); col = board[0].size(); -
从边界出发进行 BFS :分别遍历上、下、左、右四条边界,若边界格子是
'O'且未被访问,则调用bfs将该边界连通区域标记为'.'。 -
最终转换 :遍历整个矩阵,将临时标记的
'.'恢复为'O',将剩余的'O'改为'X'。
三、BFS 函数 bfs
bfs(board, i, j) 从起点 (i, j) 开始,将所有与之相连且为 'O' 的格子标记为 '.',并加入队列。执行流程如下:
-
初始化队列 :创建队列
q,将起点(i, j)入队。 -
立即标记起点 :将
board[i][j]改为'.',并设置check[i][j] = true,避免重复访问。 -
循环处理:当队列非空时:
-
取出队头坐标
(a, b)。 -
遍历四个方向,计算新坐标
(x, y)。 -
若新坐标合法、未被访问、且是
'O',则将其改为'.',标记已访问,并加入队列。
-
-
结束:队列为空时,该连通区域处理完毕。
四、关键细节
-
入队即标记 :在邻居入队前立即将其改为
'.'并标记check,避免重复入队,保证每个格子只被处理一次。 -
边界处理 :从四条边界的
'O'出发,确保所有与边界相连的'O'都被标记为临时字符。
五、流程图
