算法日常・每日刷题--<BFS>4

130. 被围绕的区域 - 力扣(LeetCode)130. 被围绕的区域 - 给你一个 m x n 的矩阵 board ,由若干字符 'X' 和 'O' 组成,捕获 所有 被围绕的区域: * 连接:一个单元格与水平或垂直方向上相邻的单元格连接。 * 区域:连接所有 'O' 的单元格来形成一个区域。 * 围绕:如果一个区域中的所有 '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']]解释:[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/

题目描述

给一个 m × n 的矩阵,矩阵由字符 'X''O' 组成,捕获所有被围绕的区域。

  • 连接:单元格上下左右相邻算作连接。
  • 区域:全部相连的O构成一块区域。
  • 被包围:如果一块区域所有O都不在矩阵边界,就代表被X完全包围,需要把这部分O原地修改成X

边界上的O一定不会被包围,和边界O连通的内部O同样不会被包围,只有完全被 X 围在里面的 O 才要替换。

注意:直接原地修改数组,不需要返回值。


做题思路

直接找被包围的O不好处理,我们逆向思考:

  1. 边界上的 O 一定不会被包围,所有和边界 O 连通的 O,也一定不会被包围。
  2. 遍历矩阵四条边界,遇到O就做 BFS,把连通的O临时标记成.(做记号,表示这部分是安全的,不能被修改)。
  3. 遍历整个矩阵做还原:
    • 仍然是O:说明没有和边界连通,是被包围的,改成X
    • .:原本是边界连通的 O,恢复回O

核心:不找被包围的,先找不会被包围的,标记之后再批量修改。

class Solution {
public:
int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    int m,n;
    void solve(vector<vector<char>>& board) {
        m=board.size();
        n=board[0].size();
        for(int j=0;j<n;j++)
        {
            if(board[0][j]=='O')
            bfs(board,0,j);
            if(board[m-1][j]=='O')
            bfs(board,m-1,j);
        }
        for(int i=0;i<m;i++)
        {
            if(board[i][0]=='O')
            bfs(board,i,0);
            if(board[i][n-1]=='O')
            bfs(board,i,n-1);
        }

        //还原
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(board[i][j]=='O')
                board[i][j]='X';
                else if(board[i][j]=='.')
                board[i][j]='O';
            }
        }
    }
    
    void bfs(vector<vector<char>>& board,int i,int j)
    {
        queue<pair<int ,int>>q;
        q.push({i,j});
       board[i][j]='.';
           
 
        while(q.size())
        {
            auto [a,b]=q.front();
            q.pop();
            for(int k=0;k<4;k++)
            {
                int x=a+dx[k];
                int y=b+dy[k];
                if(x>=0 && x<m && y>=0 && y<n && board[x][y]=='O')
                {
                    q.push({x,y});
                    board[x][y]='.';
                   
                }
            }
        }
        
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值