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

五、流程图

相关推荐
find1star19 小时前
LeetCode 141:环形链表
java·算法·leetcode·链表
迅翼SwiftWing19 小时前
编队系列(总)|固定翼编队如何实现稳定飞行?通信架构、协同算法与工程约束深度解析
算法·架构
LB211220 小时前
力扣160 21 86
算法·leetcode·职场和发展
Tairitsu_H20 小时前
[C++] 深入理解红黑树:封装set与map
开发语言·c++·set·map·红黑树·模拟实现
小智老师PMP21 小时前
2026深度解析|PMP第八版与NPDP核心侧重点本质区别(管理类证书怎么选)
开发语言·分布式·算法·职场和发展·产品经理
HugoStudio_SWAN21 小时前
洛谷 B4450 / B3867 / B3923 智慧购物、储蓄与做题——从程序到生活
c++·学习·程序人生·算法·生活
a1879272183121 小时前
【算法】动态规划第二篇:双序列 DP 三课——继承、计步与断链
算法·leetcode·动态规划·dp·回溯·暴力·算法讲解
江畔柳前堤1 天前
前台·中台·后台:2026年AI原生时代的架构全景图
开发语言·人工智能·算法·机器学习·架构·scala·ai-native
文心快码BaiduComate1 天前
2026 OPC x AI Coding 趋势案例交流会圆满落幕:一个人就一支研发团队
算法
ACM-moran1 天前
条件显化(二分单峰函数+构造数列)
算法·推公式·整数三分