leetcode刷题日记-【130. 被围绕的区域】

677 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第32天,点击查看活动详情

题目描述

给你一个 m x n 的矩阵 board ,由若干字符 'X' 和 'O' ,找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O' 用 'X' 填充。  

示例 1:

image.png

输入: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'

解题思路

给定一个二维数组board,数组中元素只包含'O','X'。将二位数数组中所有不和边界'O'直接或间接关联的'O'元素替换成'X'。

根据题意,这道题的重点就是要找出所有与边界'0'直接或间接关联的点

比如点(1,0)为'0',则与它直接关联的点有(2,0),(1,1),(0,0)。即对原坐标进行四个方向的加减(1,0),(-1,0),(0,1),(0,-1);

即上下左右四个方向,然后这几个点又有直接关联的上下左右四个点,依次类推,直到这些关联的点元素不是'O';

所以解这道题有深度优先和广度优先两种选择;

深度优先

遍历上、下、左、右边界的元素,每一次找一个方向上所有的直接或间接与'O'关联的元素,将它们替换成其它元素,比如'B';

遍历完成之后将原数组进行遍历,找到不是'B'且是'O'的元素,将它们设置成'X',然后再将元素值为'B'的替换成'O';

广度优先

第一层遍历获取上、下、左、右边界上所有的'O'元素,将它们设置成其它的元素,比如'B',将它放入队列queue中;

遍历queue,截止条件为queue为空,每一次循环从queue中弹出栈顶元素,然后对原坐标进行四个方向的加减(1,0),(-1,0),(0,1),(0,-1);

获取与当前元素直接关联的节点,判断如果计算出来的位置的元素为'O',则将这个节点的位置放入queue中,并且将该元素修改为'B';

queue队列内容为空时,即找完二维数组中所有直接或间接与边界'O'关联的元素,此时再遍历二维数组,将元素值不是'B'且元素值为'O'的元素替换成'X',然后再将元素值为'B'的替换成'O';

代码实现

public void solve(char[][] board) {
    n = board.length;
    m = board[0].length;
    // 深度优先
    // 第一层左右边界
    for (int i=0; i < n;i ++) {
        // 第一列
        dfs(board,i,0);
        // 末尾列
        dfs(board,i,m-1);
    }

    // 上下边界
    for (int i=0; i < m;i ++) {
        // 第一列
        dfs(board,0,i);
        // 末尾列
        dfs(board,n-1,i);
    }
    // System.out.print("[");
    for (int i=0;i<n;i++) {
        for (int j=0;j<m;j++) {
            if (board[i][j] != 'B') {
                board[i][j] = 'X';
            } else {
                board[i][j] = 'O';
            }
        }
        // System.out.print(Arrays.toString(board[i]));
    }
    // System.out.print("]");
}

private void dfs(char[][] board, int x, int y) {
    if (x < 0 || x >= n || y < 0 || y >= m || board[x][y] != 'O') {
        // 截止条件,四个方向的值超出矩阵范围或者当前查找元素不是目标替换元素 则直接返回
        return;
    }
    // 修改当前查找元素为'B'
    board[x][y] = 'B';
    // 递归查找四个方向的元素
    for (int[] ints : direction) {
        dfs(board,x+ints[0],y+ints[1]);
    }
}