《LeetCode 130 被围绕的区域 FloodFill DFS 解法》

一.题目

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

二.思路讲解

2.1 思路讲解

本题的难点在于直接判断一个 'O' 是否被 'X' 包围比较麻烦。我们可以采用正难则反的思想:

  • 从边界上的 'O' 出发 ,通过 DFS / BFS 将所有与边界相连的 'O' 标记为临时字符 (例如 '.')。这些 'O' 不会被包围,因为它们连接到了边界。

  • 遍历整个矩阵,剩下的 'O' 就是完全被包围的区域,将其改为 'X'。

  • 最后将临时标记的字符 恢复为 'O',即完成了"捕获被围绕的区域"。

三.代码演示

cpp 复制代码
class Solution {
public:
    int row,col;;
    int bx[4] = {0,0,1,-1};
    int by[4] = {1,-1,0,0};
    void solve(vector<vector<char>>& board) 
    {
        row = board.size(),col = board[0].size();
        for(int i = 0;i < row;i++)
        {
            for(int j = 0;j < col;j++)
            {
                //边界
                if((j == 0 || i == 0 || i == row - 1 ||j == col - 1) && board[i][j] == 'O')
                {
                    dfs(board,i,j);
                }
            }
        }
        for(int i = 0;i < row;i++)
        {
            for(int j = 0;j < col;j++)
            {
                if(board[i][j] == '.')
                    board[i][j] = 'O';
                else if(board[i][j] == 'O')
                    board[i][j] = 'X';
            }
        }
    }
    void dfs(vector<vector<char>>& board,int i,int j)
    {
        board[i][j] = '.';
        for(int k = 0;k < 4;k++)
        {
            int x = i + bx[k],y = j + by[k];
            if(x >= 0 && y >= 0 && x < row && y < col && board[x][y] == 'O')
            {
                dfs(board,x,y);
            }
        }
    }
};

四.代码讲解

一、全局变量与数据结构
  • row、col:成员变量,存储矩阵的行数和列数。

  • 方向数组 bx[4]、by[4]:表示上下左右四个方向的偏移量,用于探索相邻格子。

二、主函数 solve
  1. 获取矩阵尺寸 :row = board.size(),col = board[0].size()。

  2. 遍历边界,从边界的 'O' 开始深度优先搜索:

    • 使用双重循环遍历整个矩阵,但只在边界格子 (i == 0 或 i == row-1 或 j == 0 或 j == col-1)且当前格子为 'O' 时,调用 dfs。

    • 注意条件中的 && 与 || 优先级已用括号明确,确保只在边界且为 'O' 时进入。

  3. 第二次遍历,转换字符:

    • 遍历所有格子:

      • 如果当前格子是临时标记 '.',则恢复为 'O'(表示与边界相连的 'O',不应被捕获)。

      • 如果当前格子仍是 'O',则说明它被完全包围,改为 'X'。

      • 其他情况(原本是 'X' 或已处理的 '.')保持不变。

三、递归函数 dfs

dfs(board, i, j) 从当前格子出发,将与之相邻的 'O' 全部标记为临时字符 '.'。执行流程:

  1. 标记当前格子 :board[i][j] = '.',表示该格子与边界相连,不被捕获。

  2. 向四个方向探索 :使用 for 循环遍历四个方向,计算新坐标 (x, y)。对于每个方向,检查:

    • 边界内 :x >= 0 && y >= 0 && x < row && y < col

    • 是 'O' :board[x][y] == 'O' 如果满足条件,则递归调用 dfs(board, x, y),继续标记。

四、关键细节
  • 正难则反思想 :直接判断内部 'O' 是否被包围较复杂,改为从边界出发,标记所有不被包围的 'O',剩下的即为被包围的。

  • 临时标记 '.' :利用一个不存在于原字符集的符号(如 '.')来区分边界可达的 'O',避免使用额外 visited 数组。

  • 边界条件处理 :双重循环中只对边界格子且为 'O' 的情况启动 DFS,避免从内部 'O' 出发造成误判。

五、流程图

相关推荐
zyl7656 小时前
FlashAttention 详解:从 GPU 硬件、普通 Attention 到分块计算与 Online Softmax
算法
爱读书的小胖10 小时前
LeetCode 122:买卖股票的最佳时机 II(C)解题分析
算法
结局无敌10 小时前
React Native for OpenHarmony 实战:三方库 react-native-modal-dialog 的鸿蒙化适配指南
深度学习·算法·react native·react.js·harmonyos
OPEN-F10 小时前
ROS2系列教程:上位机建图与导航(原理综合)
算法·机器人
weixin_3077791310 小时前
C++代码实现MATLAB中的fitrtree函数功能
开发语言·c++·算法·matlab
AI wins10 小时前
c++新增頭文件
c++
Shadow(⊙o⊙)11 小时前
仿muduo实现高并发服务器——事件就绪管理Channel.hpp
服务器·c++
tomwang032211 小时前
路径优化建模、优化算法分类及工程化小结
算法·数学建模·分类
小羊没烦恼!11 小时前
Ajax与JSON的一些总结
android·java·前端·数据库·mysql·算法·okhttp
by2099911 小时前
哈希表——快速找到数据:冲突、删除与扩容的实现
数据结构·c++·哈希算法·散列表