题目:
给定一个二维的矩阵,包含 'X'
和 'O'
(字母 O)。
找到所有被 'X'
围绕的区域,并将这些区域里所有的 'O'
用 'X'
填充。
示例:
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'。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
分析:
根据题意可知,任何不在边界上,或不与边界上的 'O' 相连的 'O' 最终都会被填充为 'X'。那也就是说,边界上的‘O’以及与其相邻的‘O’都不能填充为‘X’,如果单纯的去找被围绕的‘O’,且不与边界“O”相邻,是比较麻烦的,需要一个一个去遍历内部的元素,寻找连通分量,同时还要保证寻找的连通分量中不能有与边界“O”相邻的。那我们就直接去遍历位于边界上的元素,凡是遇到值为‘O’的元素就开始进行深度优先遍历,遍历得到的连通分量都是不能进行X填充的,这里我们用一个和board同样大小的访问标记数组去标记被访问过且值为‘O’的元素,这些都是要保持不变的元素。完成所有这些遍历之后,再对访问标记数组进行遍历,凡是遇到值为‘O’同时在访问标记数组中对应位置的值为false的元素时,就是要进行填充‘X’的元素。
代码:
private int row;
private int col;
private int[][] dir;
private boolean[][] isVisited;
public void solve(char[][] board) {
if (board == null || board.length<=1 || board[0].length <= 1){
return;
}
dir = new int[][]{{1,0},{-1,0},{0,1},{0,-1}};
row = board.length;
col = board[0].length;
isVisited = new boolean[row][col];
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if ((i ==0 || j == 0 || i == row-1 || j == col-1) && board[i][j] == 'O' && !isVisited[i][j]){
findOByDFS(board,i,j);
}
}
}
for (int i = 0; i < isVisited.length; i++) {
for (int i1 = 0; i1 < isVisited[0].length; i1++) {
if (board[i][i1]=='O' && !isVisited[i][i1]){
board[i][i1] = 'X';
}
}
}
}
private void findOByDFS(char[][] board, int i, int j) {
if (i >= row || i < 0 || j>=col || j<0 || isVisited[i][j] || board[i][j]=='X'){
return;
}
isVisited[i][j] = true;
for (int[] ints : dir) {
findOByDFS(board,i+ints[0],j+ints[1]);
}
}