《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' 出发造成误判。

五、流程图

相关推荐
林森lsjs1 小时前
斐波那契数列的 N 种解法:从递归到动态规划的优化之路【算法思考】
算法·动态规划
apcipot_rain2 小时前
计科八股20260616(1)——堆存中位数、链表判环、黑白测试、敏捷开发与瀑布模型、配置管理、持续集成、池化
数据结构·算法·软件工程
一只旭宝9 小时前
【C++入门精讲22】常见设计模式
c++·设计模式
JAVA面经实录9179 小时前
Java 数据结构与算法 (终极完整学习文档)
java·数据结构·算法
c++之路10 小时前
Bazel C++ 构建系列文档(三):构建第一个 C++ 项目
开发语言·c++
开源Z10 小时前
LeetCode 42 · 接雨水:从暴力到双指针的三步优化
算法·leetcode
旖-旎10 小时前
《LeetCode 695 岛屿的最大面积 FloodFill DFS 解法》
c++·算法·力扣·深度优先遍历·floodfill
森G11 小时前
61、信号与槽机制在 TCP 编程中的应用---------网络编程
网络·c++·qt·网络协议·tcp/ip
syagain_zsx11 小时前
STL 之 vector 讲练结合
c++·算法