《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);
            }
        }
    }
};

四.代码讲解

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

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

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

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

    • 使用双重循环遍历整个矩阵,但只在边界格子i == 0i == row-1j == 0j == 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' 出发造成误判。

五、流程图

相关推荐
王维同学6 小时前
Winsock 协议与名称空间 Provider 目录
网络·c++·windows·安全
拳里剑气7 小时前
C++算法:BFS解决FloodFill算法
c++·算法·bfs·宽度优先
爱写代码的小朋友7 小时前
从零开始学 Win32 API:C++ 窗口编程实战(VS Code + MinGW-w64 命令行详解)
开发语言·c++
小小晓.8 小时前
C++:语句和作用域
开发语言·c++
fqbqrr8 小时前
2607C++,soui,xplayer视频播放器
c++·soui
wanderist.9 小时前
Lambda表达式在算法竞赛中的应用
java·开发语言·算法
zh路西法9 小时前
【10天速通ROS2-PX4无人机】(四) 关掉GPS和气压计,纯激光定位还能飞吗
c++·无人机·px4·ros2·卡尔曼滤波·fastlio2
稚南城才子,乌衣巷风流9 小时前
支配树(Dominator Tree)详解:概念、算法与应用
算法
稚南城才子,乌衣巷风流10 小时前
动态开点:原理、实现与应用场景
数据结构·算法