32.被围绕的区域(medium)

1.题目链接:130. 被围绕的区域 - 力扣(LeetCode)130. 被围绕的区域 - 给你一个 m x n 的矩阵 board ,由若干字符 'X' 和 'O' 组成,捕获 所有 被围绕的区域: * 连接:一个单元格与水平或垂直方向上相邻的单元格连接。 * 区域:连接所有 'O' 的单元格来形成一个区域。 * 围绕:如果您可以用 'X' 单元格 连接这个区域,并且区域中没有任何单元格位于 board 边缘,则该区域被 'X' 单元格围绕。通过 原地 将输入矩阵中的所有 'O' 替换为 'X' 来 捕获被围绕的区域。你不需要返回任何值。 示例 1:输入: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"]]解释:[https://pic.leetcode.cn/1718167191-XNjUTG-image.png]在上图中,底部的区域没有被捕获,因为它在 board 的边缘并且不能被围绕。示例 2:输入:board = [["X"]]输出:[["X"]] 提示: * m == board.length * n == board[i].length * 1 <= m, n <= 200 * board[i][j] 为 'X' 或 'O'https://leetcode.cn/problems/surrounded-regions/description/

2.题目描述:

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

示例 1:​

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

3. 解法:

算法思路:

正难则反。

可以先利用 dfs  将与边缘相连的 '0'  区域做上标记,然后重新遍历矩阵,将没有标记过的 '0'

修改成 'X'  即可。​

Java算法代码:

class Solution {
    int m,n;
    int [] dx = {1,-1,0,0};
    int [] dy = {0,0,1,-1};
    public void solve(char[][] board) {
        m = board.length;n = board[0].length;

        //1.先把边界的O相连的连通块,全部修改为'.'
        for(int j = 0; j<n;j++){
            if(board[0][j] =='O') dfs(board,0,j);
            if(board[m-1][j] =='O') dfs(board,m-1,j);
        }
        for(int i = 0; i<m;i++){
            if(board[i][0] =='O') dfs(board,i,0);
            if(board[i][n-1] =='O') dfs(board,i,n-1);
        }
        //2.还原(因为是修改为第三种记号,所以还是可以还原的)
        for(int i = 0;i<m;i++)
            for(int j = 0;j<n;j++)
                if(board[i][j] == '.') board[i][j] ='O';
                else if(board[i][j] == 'O') board[i][j] ='X';
    }
    public void dfs(char[][]board ,int i,int j){
        board[i][j] = '.';
        for(int k =0;k<4;k++){
            int x = i + dx[k], y = j + dy[k];
            if(x >= 0 && x < m && y >= 0 && y < n && board[x][y] == 'O'){
                dfs(board, x, y);
            }
        }
    }
}

运行结果:

递归展开:

逻辑展开:

这里需要注意的是,逻辑上明白了,做题的全流程。

细节都在上面的展开中(比如,遍历顺序之类的)

---------------------------------------------------------------------------------------------------------------------------------

记住,相信你的递归函数,它可以做到!

记住,不理解时候,去尝试手动展开!

记住,逻辑展开(你不可能对所有的题目都进行手动展开)!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值