算法日常・每日刷题--<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 == boardi.length * 1 <= m, n <= 200 * boardij 为 '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

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

cpp 复制代码
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]='.';
                   
                }
            }
        }
        
    }
};
相关推荐
y1su1 小时前
Leetcode 字符串模板
java·数据结构·算法·leetcode·职场和发展·动态规划
residual_fan1 小时前
船用柴油机动态机动工况故障诊断:控制感知仿射网络(CAAN)的技术实现
人工智能·算法·数据挖掘·数据分析
其实防守也摸鱼2 小时前
Cylab在线靶场——CTF中的通用技能
linux·数据库·学习·算法·靶场·ctf·学习网络安全
蓝悦无人机2 小时前
《Planning algorithms》读书笔记——第8章 反馈运动规划
算法·读书笔记·反馈运动规划
RaaS1002 小时前
Agent Skills 进了 Linux Foundation:2.8 亿次安装,但装 skill 还没有安全规范
人工智能·算法·架构
CV爱数码3 小时前
CT 重建从零开始(五):ASTRA Toolbox 上手——几何、投影器与算法
图像处理·算法·计算机视觉·ct
TunerT_TQ3 小时前
超立方体Ramsey(openai/math 家族171)H11攻坚日志|D60–D69:Star分组重数、二幂坐标群、奇偶入射语义与Site‑Level候选计数形式化闭环
算法
Rabitebla3 小时前
【系统性学习笔记】Linux 权限篇(二):文件属性、权限修改与目录权限的底层逻辑
linux·c++·笔记·学习·算法
远离UE43 小时前
半拉格朗日学习笔记 动力学 实时渲染
人工智能·算法
小郎君6584 小时前
MPTT 不是万能编号:一棵百万节点树的增删改与批量事务
算法