给你一个 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.lengthn == board[i].length1 <= m, n <= 200board[i][j]为'X'或'O'
解题思路:正难则反
这道题如果我们直接像岛屿问题那样,用深度优先遍历进行处理,其实是比较难搞定的,此时一个
dfs()函数是不够的! 因为我们在遍历的时候,如果遍历到被围绕的区域,那么做法是将其元素都修改为
X,而如果是边界区域的话,则要保留其元素为O,但是有个问题,就是在深度优先遍历的时候,虽然我们遇到边界的时候可以判断当前区域就是边界区域,但是有可能当前遍历的元素是边界区域的内部,也就是不在边界上,但在边界区域内的元素,此时就算我们用一个全局变量is_surround来标记后面递归可能会遇到的边界,但是有可能当前元素已经把递归步骤走完并且在遇到边界之前就将其修改为X了,此时就算后面其它路径遇到了边界,将is_surround改成true,此时对于当前元素也无力回天了! 除非我们搞两个不同的递归函数,一个是将
O变成X的,一个是判断是否为边界区域的,只有我们先处理完是否为边界区域的操作,再去判断是否要进行将O变成X的操作,才是正确的,但是搞两个不同的递归函数其实挺冗余的,所以这里我们换个思路走!
这个思路就是正难则反,并不是说要将 X 变成 O,而是说可以先处理二维数组边界上的边界区域,将它们从 O 先变成一个其它的字符,这里我们就将其变成 . 字符。
为什么这么做呢❓❓❓
当我们先处理完边界区域之后,此时边界区域的元素都变成了 .,而那些不是边界区域的元素,还是 O,那么最后我们只需要遍历一下二维数组,将 O 元素变成 X,就可以达到将非边界区域都变成 X 的目的;而对于 . 字符来说,它们就是边界区域的元素,所以将其还原成 O 即可!
而剩下的操作都是类似的,具体可以参考下面代码:
class Solution {
public:
void solve(vector<vector<char>>& board) {
int m = board.size(), n = board[0].size();
// 1. 将与边界上'O'相连的区域变成'.'
for(int i = 0; i < m; ++i)
{
if(board[i][0] == 'O') dfs(board, i, 0);
if(board[i][n - 1] == 'O') dfs(board, i, n - 1);
}
for(int j = 0; j < n; ++j)
{
if(board[0][j] == 'O') dfs(board, 0, j);
if(board[m - 1][j] == 'O') dfs(board, m - 1, j);
}
// 2. 将'.'的区域还原成'O',将'O'区域变成'X'
for(int i = 0; i < board.size(); ++i)
{
for(int j = 0; j < board[i].size(); ++j)
{
if(board[i][j] == 'O') board[i][j] = 'X';
if(board[i][j] == '.') board[i][j] = 'O';
}
}
}
// 将'O'变成'.'的递归函数
void dfs(vector<vector<char>>& board, int x, int y)
{
// 递归函数出口
if(x < 0 || x == board.size() || y < 0 || y == board[x].size() || board[x][y] == 'X' || board[x][y] == '.')
return;
board[x][y] = '.';
dfs(board, x + 1, y);
dfs(board, x - 1, y);
dfs(board, x, y + 1);
dfs(board, x, y - 1);
}
};