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’
中,被‘X’
包围的所有‘O’
。那么怎么判定是否被包围呢?通过观察,我们发现,一旦有‘O’
的区域是不被包围的,则代表这片‘O’
区域一定会和区域的边界连接,一旦会连接,则代表边界上是有‘O’
的,这样才可导致其不被包围,反之则一定会被包围。
得到此关键因素后,我们就可以容易的想出以下思路:
- 先对边界进行遍历查找,查找是否有
‘O’
的元素; - 对在边界上查找到的
‘O’
,进行dfs
查找,将与其连续的都查找出来,并将这些区域都改为‘N’
,代表其是不被包围的‘O’
区域; - 边界查找完毕后,我们重新遍历整个区域,一旦发现还是有
‘O’
存在,则一定是被包围的‘O’
区域,因此直接改为‘X’
即可,因为没有被包围‘O’
区域的我们都改写为了‘N’
; - 对所有的
‘N’
进行还原,还原为‘O’
;
主体思路就是先找出不被包围的‘O’
区域,将他们做上标记,接着遍历数组碰到‘O’
就改成‘X’
即可,即可完成对被包围区域的重新填充,最后再还原标记即可。先从不被包围的‘O’
区域入手是因为其好找,一定起点在边界出发。
JAVA代码:
class Solution {
public void solve(char[][] board) {
for(int i=0;i<board[0].length;i++){
if(board[0][i]=='O'){
dfs(board,0,i);
}
}
for(int i=0;i<board.length;i++){
if(board[i][board[0].length-1]=='O'){
dfs(board,i,board[0].length-1);
}
}
for(int i=0;i<board[0].length;i++){
if(board[board.length-1][i]=='O'){
dfs(board,board.length-1,i);
}
}
for(int i=0;i<board.length;i++){
if(board[i][0]=='O'){
dfs(board,i,0);
}
}
for(int i=0;i<board.length;i++){
for(int j=0;j<board[0].length;j++){
if(board[i][j]=='O'){
board[i][j]='X';
}
if(board[i][j]=='N'){
board[i][j]='O';
}
}
}
}
public void dfs(char[][] board,int i,int j){
if(i<0 || j<0 ||
i>board.length-1 || j>board[0].length-1 || board[i][j]!='O'){
return;
}
board[i][j] = 'N';
dfs(board,i+1,j);
dfs(board,i,j+1);
dfs(board,i-1,j);
dfs(board,i,j-1);
}
}