题目描述:
给定一个二维的矩阵,包含 ‘X’ 和 ‘O’(字母 O)。
找到所有被 ‘X’ 围绕的区域,并将这些区域里所有的 ‘O’ 用 ‘X’ 填充。
思路分析:
该题和岛屿数量特别相似,这道题的难点在于边界的0和内部多个0的连通情况的处理,如下图:
底部边界的0和内部的0是连通的,所以都不需要把这些0改为X。
(1)我们可以对边界进行dfs遍历,将所有的连通的0找到,改为字母‘A’;
(2)遍历数组,遇到元素’0’,改为’X’,遇到元素‘A’,改为’0’
可知‘A’是不需要修改的,所以要改回去。
参考代码:
public void solve(char[][] board) {
if(board == null || board.length == 0)return;
int m = board.length;
int n = board[0].length;
//将左边界和右边界所有的0的连通全改为'A'
for(int i = 0; i < m; i++){
dfs(board, i, 0);
dfs(board, i, n - 1);
}
//将上边界和下边界所有的0的连通全改为'A'
for(int i = 1; i < n - 1; i++){//这里注意,上面计算时把i=0和i=n-1都计算了
dfs(board, 0, i);
dfs(board, m - 1, i);
}
//将‘A’改回‘O’,将要改的‘O’改为‘X’
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(board[i][j] == 'A')board[i][j] = 'O';
else if(board[i][j] == 'O')board[i][j] = 'X';
}
}
}
//dfs找到所有的0连通元素,改为‘A’
public void dfs(char[][] board, int i, int j){
if(i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] != 'O')return;//这里注意:不能写成board[i][j] == 'X'
if(board[i][j] == 'O')board[i][j] = 'A';//关键代码
dfs(board, i + 1, j);
dfs(board, i - 1, j);
dfs(board, i, j + 1);
dfs(board, i, j - 1);
}
小结:
dfs中的判断条件中:board[i][j] != 'O’不能改为 board[i][j] == ‘X’,如果改为后者,则对于如下的情况,将所有的‘O’改为‘A’后,board[i][j] == 'X’才返回,因为‘A’ != ‘X’,所以会一直进行递归: