力扣【广度搜索专题】👊 130. 被围绕的区域

160 阅读2分钟

「这是我参与2022首次更文挑战的第 17 天,活动详情查看:2022首次更文挑战

题目链接

130. 被围绕的区域 - 力扣(LeetCode) (leetcode-cn.com)

题目描述

给你一个 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'。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。

条件限制

  • m == board.length
  • n == board[i].length
  • 1 <= m, n <= 200
  • board[i][j] 为 'X' 或 'O'

题目分析

在一个 m * n 的矩阵里,每个元素都会被填充为 XO,对于四周边界上的 O 以及与之关联的 O 都需要保留下来,其他的元素需要将值都替换为 X

一个常规的思路,就是完整的遍历这个二维数组,记录下已经遍历过的坐标,当遇到值为 O 时,尝试向四周遍历查找同样为 O 且还未被遍历过的坐标,直到遍历到再也找不到为 O 的坐标,记录最后终止的 O 的坐标是否在四周的边界上:如果在边界上,这些 O 坐标就不需要处理,否则就需要全部修改为 X,当所有的坐标都遍历完成处理好后,返回原数组就行

这里分享第二种解法:尝试遍历四周的坐标,如果找到了坐标为 O 的,再通过深度搜索的方式找到坐标同样为 O 的,将这些坐标都标记为临时的值,如 T。然后矩阵里还未被修改的 O 就是需要我们修改为X。最后我们完整的遍历一次矩阵,调整坐标的值 O -> x, T -> O 即可

代码实现

/**
 * @param {character[][]} board
 * @return {void} Do not return anything, modify board in-place instead.
 */
// m 行,n 列
var solve = function(board) {
    let m = board.length,
        n = board[0].length;
    // 遍历四周一圈,将关联的 O => T
    [0, m - 1].forEach(row => {
        for (let j = 0; j < n; j++) {
            trave(board, row, j);
        }
    });
    [0, n - 1].forEach(col => {
        for (let i = 0; i < m; i++) {
            trave(board, i, col);
        }
    });
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if (board[i][j] == 'O') board[i][j] = 'X';
            if (board[i][j] == 'T') board[i][j] = 'O';
        }
    }
    return board;

    function trave(arrs, i, j) {
        if (arrs[i][j] != 'O') return;
        arrs[i][j] = 'T';
        if (i > 0) trave(arrs, i - 1, j);
        if (i < m - 1) trave(arrs, i + 1, j);
        if (j > 0) trave(arrs, i, j - 1);
        if (j < n - 1) trave(arrs, i, j + 1);
    }
};

image.png

解法1比较常规,且需要我们记录下已经遍历的坐标,并且涉及到递归和回溯操作,比较繁琐且需要额外的空间来记录已经遍历的值

解法2 就有点取巧了,第一个只遍历四周坐标+深度搜索相关坐标再标记区分需要保留的坐标值,第二次才会完整的遍历整个矩阵再统一调整整个矩阵的值,思路简单明了且不需要额外的空间