题目描述
题目链接:leetcode 130. 被围绕的区域
给你一个 m x n 的矩阵 board ,由若干字符 ‘X’ 和 ‘O’ ,找到所有被 ‘X’ 围绕的区域,并将这些区域里所有的 ‘O’ 用 ‘X’ 填充。
示例 1:
输入:board = [[“X”,“X”,“X”,“X”],[“X”,“O”,“O”,“X”],[“X”,“X”,“O”,“X”],[“X”,“O”,“X”,“X”]]
输出:[[“X”,“X”,“X”,“X”],[“X”,“X”,“X”,“X”],[“X”,“X”,“X”,“X”],[“X”,“O”,“X”,“X”]]
解释:被围绕的区间不会存在于边界上,换句话说,任何边界上的 ‘O’ 都不会被填充为 ‘X’。 任何不在边界上,或不与边界上的 ‘O’ 相连的 ‘O’ 最终都会被填充为 ‘X’。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
示例 2:
输入:board = [[“X”]]
输出:[[“X”]]
提示:
- m == board.length
- n == board[i].length
- 1 <= m, n <= 200
- board[i][j] 为 ‘X’ 或 ‘O’
思路
不会被"X"包围的“O”要么是矩阵边界上的“O”,要么就是和边界上的“O”连通的“O”。故只需要找到边界上的“O”,以边界上的“O”为起点搜索与其连通的“O”并做上标记。最后没有被标记的点要么是“X”,要么是可以被“X”包围的“O”,通通赋值为“X”即可。
C++代码
//xx和yy的组合构成四个方向
int xx[4]={0,1,0,-1};
int yy[4]={1,0,-1,0};
class Solution {
public:
void dfs(vector<vector<char>>& board,vector<vector<bool>> &vis,int m,int n,int x,int y){
vis[x][y]=true;
//遍历可以走的四个方向
for(int i=0;i<4;i++){
int _x=x+xx[i];
int _y=y+yy[i];
if(_x<0||_y<0||_x>=m||_y>=n) continue; //越界就不能走
if(!vis[_x][_y]&&board[_x][_y]=='O'){
dfs(board,vis,m,n,_x,_y);
}
}
}
void solve(vector<vector<char>>& board) {
int m=board.size();
int n=board[0].size();
//标记数组,false表示和边界上的"O"不连通
vector<vector<bool>>vis(m,vector<bool>(n,false));
//找到第一列的"O",搜索和他连通的"O"并标记
for(int i=0;i<m;i++)
if(board[i][0]=='O'&&!vis[i][0]) dfs(board,vis,m,n,i,0);
//找到最后一列的"O",搜索和他连通的"O"并标记
for(int i=0;i<m;i++)
if(board[i][n-1]=='O'&&!vis[i][n-1]) dfs(board,vis,m,n,i,n-1);
//找到第一行的"O",搜索和他连通的"O"并标记
for(int j=0;j<n;j++)
if(board[0][j]=='O'&&!vis[0][j]) dfs(board,vis,m,n,0,j);
//找到最后一行的"O",搜索和他连通的"O"并标记
for(int j=0;j<n;j++)
if(board[m-1][j]=='O'&&!vis[m-1][j]) dfs(board,vis,m,n,m-1,j);
//没有被标记的全部赋值为"X"
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(!vis[i][j]) board[i][j]='X';
}
}
}
};