一.题目

二.思路讲解
2.1 思路讲解
本题的难点在于直接判断一个 'O' 是否被 'X' 包围比较麻烦。我们可以采用正难则反的思想:
-
从边界上的
'O'出发 ,通过 DFS / BFS 将所有与边界相连的'O'标记为临时字符 (例如'.')。这些'O'不会被包围,因为它们连接到了边界。 -
遍历整个矩阵,剩下的
'O'就是完全被包围的区域,将其改为'X'。 -
最后将临时标记的字符 恢复为
'O',即完成了"捕获被围绕的区域"。
三.代码演示
cpp
class Solution {
public:
int row,col;;
int bx[4] = {0,0,1,-1};
int by[4] = {1,-1,0,0};
void solve(vector<vector<char>>& board)
{
row = board.size(),col = board[0].size();
for(int i = 0;i < row;i++)
{
for(int j = 0;j < col;j++)
{
//边界
if((j == 0 || i == 0 || i == row - 1 ||j == col - 1) && board[i][j] == 'O')
{
dfs(board,i,j);
}
}
}
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 dfs(vector<vector<char>>& board,int i,int j)
{
board[i][j] = '.';
for(int k = 0;k < 4;k++)
{
int x = i + bx[k],y = j + by[k];
if(x >= 0 && y >= 0 && x < row && y < col && board[x][y] == 'O')
{
dfs(board,x,y);
}
}
}
};
四.代码讲解
一、全局变量与数据结构
-
row、col:成员变量,存储矩阵的行数和列数。 -
方向数组
bx[4]、by[4]:表示上下左右四个方向的偏移量,用于探索相邻格子。
二、主函数 solve
-
获取矩阵尺寸 :
row = board.size(),col = board[0].size()。 -
遍历边界,从边界的
'O'开始深度优先搜索:-
使用双重循环遍历整个矩阵,但只在边界格子 (
i == 0或i == row-1或j == 0或j == col-1)且当前格子为'O'时,调用dfs。 -
注意条件中的
&&与||优先级已用括号明确,确保只在边界且为'O'时进入。
-
-
第二次遍历,转换字符:
-
遍历所有格子:
-
如果当前格子是临时标记
'.',则恢复为'O'(表示与边界相连的'O',不应被捕获)。 -
如果当前格子仍是
'O',则说明它被完全包围,改为'X'。 -
其他情况(原本是
'X'或已处理的'.')保持不变。
-
-
三、递归函数 dfs
dfs(board, i, j) 从当前格子出发,将与之相邻的 'O' 全部标记为临时字符 '.'。执行流程:
-
标记当前格子 :
board[i][j] = '.',表示该格子与边界相连,不被捕获。 -
向四个方向探索 :使用
for循环遍历四个方向,计算新坐标(x, y)。对于每个方向,检查:-
边界内 :
x >= 0 && y >= 0 && x < row && y < col -
是
'O':board[x][y] == 'O'如果满足条件,则递归调用dfs(board, x, y),继续标记。
-
四、关键细节
-
正难则反思想 :直接判断内部
'O'是否被包围较复杂,改为从边界出发,标记所有不被包围的'O',剩下的即为被包围的。 -
临时标记
'.':利用一个不存在于原字符集的符号(如'.')来区分边界可达的'O',避免使用额外visited数组。 -
边界条件处理 :双重循环中只对边界格子且为
'O'的情况启动 DFS,避免从内部'O'出发造成误判。
五、流程图
