【leetcode】130. 被围绕的区域

97 阅读2分钟

leetcode-130.png

这题的思路和lc-200有相似之处,依旧是通过 DFS(或 BFS)来“遍历连通区域并做标记”。但与 200 不同的是,这道题需要我们区分  “被包围的 O”  和  “未被包围的 O”

解题思路

  • 首先从边界出发,将所有与边界 'O' 相连的 'O' 都标记为 '#'

  • 然后遍历整个棋盘:

    • 剩余的 'O' 就是被包围的,修改为 'X'
    • 标记过的 '#' 恢复为 'O'

DFS

var solve = function (board) {
    let row = board.length;
    let col = board[0].length;
    var dfs = function (i, j) {
        if (i < 0 || i >= row || j < 0 || j >= col) return;
        if (board[i][j] !== "O") return;
        board[i][j] = "#";
        dfs(i, j - 1);
        dfs(i, j + 1);
        dfs(i - 1, j);
        dfs(i + 1, j);
    };
    // 左右边界修改为 #
    for (let i = 0; i < row; ++i) {
        dfs(i, 0);
        dfs(i, col - 1);
    }
    // 上下边界修改为 #
    for (let j = 0; j < col; ++j) {
        dfs(0, j);
        dfs(row - 1, j);
    }
    for (let i = 0; i < row; ++i) {
        for (let j = 0; j < col; ++j) {
            if(board[i][j] === 'O'){
                // 内部的 O 改为 X
                board[i][j] = 'X'
            }else if(board[i][j] === '#'){
                // 还原
                board[i][j] = 'O'
            }
        }
    }
};

BFS

var solve = function (board) {
    let row = board.length;
    let col = board[0].length;
    let directions = [[-1, 0], [1, 0], [0, -1], [0, 1]]
    var bfs = function (i, j) {
        // 保证边界上是 O 开始
        if(board[i][j] !== 'O') return
        board[i][j] = '#';
        let queue = [[i, j]]
        while(queue.length){
            let [x, y] = queue.shift()
            for(let [dx, dy] of directions){
                let fx = dx + x
                let fy = dy + y
                if(fx >= 0 && fx < row && fy >= 0 && fy < col && board[fx][fy] === 'O'){
                    queue.push([fx, fy])
                    board[fx][fy] = '#'
                }
            }
        }
    };
    // 左右边界修改为 #
    for (let i = 0; i < row; ++i) {
        bfs(i, 0);
        bfs(i, col - 1);
    }
    // 上下边界修改为 #
    for (let j = 0; j < col; ++j) {
        bfs(0, j);
        bfs(row - 1, j);
    }
    for (let i = 0; i < row; ++i) {
        for (let j = 0; j < col; ++j) {
            if(board[i][j] === 'O'){
                // 内部的 O 改为 X
                board[i][j] = 'X'
            }else if(board[i][j] === '#'){
                // 还原
                board[i][j] = 'O'
            }
        }
    }
};

✅ DFS vs BFS 对比

方式原理特点推荐使用场景
DFS递归遍历实现简单,但递归深度大时可能栈溢出连通性判断、路径查找
BFS队列逐层扩展更适合最短路径、多点并发扩展需要层次处理的题目,如迷宫、岛屿