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

五、流程图

相关推荐
硕风和炜21 小时前
【LeetCode: 1301. 最大得分的路径数目 + DP】
java·算法·leetcode·动态规划·dp·记忆化搜索
用户990450177800921 小时前
做了一个AI诊断,参考倪海厦中医理论,科学养生
算法
努力中的编程者1 天前
STL-vector的模拟实现
开发语言·c++·算法·stl·vector
没文化的阿浩1 天前
【C++】详解继承机制
开发语言·c++
weixin_400005601 天前
RL-frenet-trajectory-planning-in-CARLA
人工智能·深度学习·算法·机器学习·自动驾驶
Keven_111 天前
AcWing算法提高课思路速查:动态规划
算法·动态规划
剑挑星河月1 天前
94.二叉树的中序遍历
java·算法·leetcode
拳里剑气1 天前
C++算法:队列与BFS
c++·算法·bfs·宽度优先·队列
aaPIXa6221 天前
C++模板元编程:在编译期完成计算,实现零运行时开销
java·开发语言·c++
Ivanqhz1 天前
注意力机制
线性代数·算法·矩阵·哈希算法·dnn