被围绕的区域(力扣第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]);
        }
    }
原文地址:https://www.cnblogs.com/yxym2016/p/13170036.html