被围绕的区域(力扣第130题)
题目:
给定一个二维的矩阵,包含 '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]); } }