题目
给你一个 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”]]
-
分析
- 与边界相连的O都不会被填充成X,其余的O都会被填充成X
- 即将所有的O分成两类,一类要改为X,一类不变,不变的用#标记
- 依次从边界上的每一个O开始查找,把与它相连的O改成#。全部搜索完后,遍历矩阵,将O改为X,将#改为O
-
方法一:BFS
class Solution {
public:
void solve(vector<vector<char>>& board) {
if(board.empty()) return;//如果矩阵为空,直接返回
int row=board.size(), col=board[0].size();
//遍历左右两列,以每一个O为起点进行BFS
for(int i=0; i<row; ++i){
if(board[i][0]=='O') bfs(board, i,0);
if(board[i][col-1]=='O') bfs(board, i, col-1);
}
//遍历左右两行,以每一个O为起点进行BFS
for(int j=0; j<col; ++j){
if(board[0][j]=='O') bfs(board, 0, j);
if(board[row-1][j]=='O') bfs(board, row-1, j);
}
//遍历矩阵,修改标志位
for(int i=0; i<row; ++i){
for(int j=0; j<col; ++j){
if(board[i][j]=='O') board[i][j]='X';
if(board[i][j]=='#') board[i][j]='O';
}
}
}
private:
//bfs,传入矩阵的引用以及节点的坐标搜索以该节点为起点周围所有的O
void bfs(vector<vector<char>>& board, int i, int j){
int row = board.size(), col = board[0].size();
queue<pair<int, int>> que;
que.push({i, j});
while(!que.empty()){//队列实现BFS
auto temp = que.front();
que.pop();
int x= temp.first, y=temp.second;
if(x<0 || x==row || y<0 || y==col || board[x][y]!='O') continue;
board[x][y]='#';
que.push({x-1,y});
que.push({x+1, y});
que.push({x,y-1});
que.push({x,y+1});
}
}
};
-
时间复杂度O(m*n)
-
空间复杂度O(m*n)
-
思路
- 遍历第一行和最后一行,如果当前位置为O,就把该节点的坐标作为起点进行BFS
- 遍历第一列和最后一列,如果当前位置为O,就把该节点的坐标作为起点进行BFS
- 遍历整个矩阵,如果当前位置为O就把它改为X,如果当前位置为#就把它改为O
- BFS
- 传入三个参数,分别为矩阵的引用以及坐标
- 建队列,元素为pair,将初始坐标入队列。如果队列不为空,依次处理每一个节点
- 记录队首元素的坐标x和y,将该节点出队列。如果超出矩阵的下标范围或者当前位置元素不是O,就跳过当前循环。此处不能判断元素等于X,否则会漏掉元素为#的情况,导致节点重复入队列造成循环
- 如果循环继续,则表示当前节点为O,将它改为#,然后将它的四个方向入队列
-
方法二:DFS
class Solution {
public:
void solve(vector<vector<char>>& board) {
if(board.empty()) return;
int row=board.size(), col=board[0].size();
for(int i=0; i<row; ++i){
if(board[i][0]=='O') dfs(board, i,0);
if(board[i][col-1]=='O') dfs(board, i, col-1);
}
for(int j=0; j<col; ++j){
if(board[0][j]=='O') dfs(board, 0, j);
if(board[row-1][j]=='O') dfs(board, row-1, j);
}
for(int i=0; i<row; ++i){
for(int j=0; j<col; ++j){
if(board[i][j]=='O') board[i][j]='X';
if(board[i][j]=='#') board[i][j]='O';
}
}
}
private:
//传入的参数为当前矩阵的引用,当前节点的坐标
void dfs(vector<vector<char>>& board, int i, int j){
//递归边界
if(i<0||i==board.size()||j<0||j==board[0].size()||board[i][j]!='O')
return;
//当前节点为O,修改为#,递归搜索它的四个方向
board[i][j]='#';
dfs(board,i-1,j);
dfs(board,i+1,j);
dfs(board,i,j-1);
dfs(board,i,j+1);
}
};
- 时间复杂度O(m*n)
- 空间复杂度O(m*n)
- 思路
- 同BFS,只有遍历修改标识位不同
- DFS
- 判断递归边界:如果超出了矩阵的表示范围,或者当前节点不是O,直接返回
- 处理当前节点,将O修改为#,递归搜索它的四个方向