《LeetCode 200 FloodFill 岛屿数量DFS解法》

一.题目

200. 岛屿数量 - 力扣(LeetCode)

二.思路讲解

2.1 思路讲解

FloodFill(洪水灌溉) 系列的题目,同样可以采取深搜的方式处理,但与常规回溯算法有一个最显著的区别:不需要恢复现场 。回溯中的"恢复现场"是为了尝试其他分支,而 FloodFill 是一次性将整个连通区域填满 ,走过的格子被永久修改(例如将 '1' 改为 '0'),因此不需要再撤销操作。这就像真正的洪水灌溉,水流经过的地方就被覆盖了,不会再变回原样。

三.代码演示

cpp 复制代码
class Solution 
{
public:
    int ret;
    int row,col;
    bool check[301][301];
    int bx[4] = {0,0,1,-1};
    int by[4] = {1,-1,0,0};
    int numIslands(vector<vector<char>>& grid) 
    {
        //初始化
        row = grid.size(),col = grid[0].size();
        for(int i = 0;i < row;i++)
        {
            for(int j = 0;j < col;j++)
            {
                if(grid[i][j] == '1' && !check[i][j])
                {
                    dfs(grid,i,j);
                    ret++;
                }
            }
        }    
        return ret;
    }
    void dfs(vector<vector<char>>& grid,int i,int 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 && !check[x][y] && grid[x][y] == '1')
            {
                check[x][y] = true;//占用
                dfs(grid,x,y);
            }
        }
    }
};

四.代码讲解

一、全局变量与数据结构
  • ret:整型变量,记录岛屿数量,初始为 0。

  • row、col:成员变量,存储网格的行数和列数。

  • check[301][301]:布尔数组,记录每个格子是否已被访问过,避免重复遍历。大小 301 足以应对常见数据范围。

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

二、主函数 numIslands
  1. 获取网格的行数 row 和列数 col。

  2. 遍历整个网格,对于每个格子 (i, j):

    • 如果当前格子是陆地 '1' 且未被访问过(!check[i][j]),则说明发现了一个新的岛屿。

    • 调用递归函数 dfs 从该格子开始进行深度优先搜索,将整个岛屿的陆地全部标记为已访问。

    • 岛屿计数 ret 加 1。

  3. 遍历结束后,返回岛屿数量 ret。

三、递归函数 dfs

dfs(grid, i, j) 的作用是:从当前格子 (i, j) 出发,向四个方向探索,将所有与之相连的陆地格子标记为已访问。注意:当前格子本身也需要标记,否则会导致重复访问和死循环。但原代码在调用前并未标记起点,这是一个潜在错误,应修正。正确流程如下:

1. 标记当前格子

首先将当前格子标记为已访问(check[i][j] = true)。这是洪水灌溉的关键,保证每个格子只被处理一次。

2. 向四个方向探索

使用 for 循环遍历四个方向,计算新坐标 (x, y)。对于每个方向,检查该格子是否合法:

  • 边界检查 :x >= 0 && y >= 0 && x < row && y < col。

  • 未访问 :!check[x][y]。

  • 是陆地 :grid[x][y] == '1'。

如果条件满足,则递归调用 dfs(grid, x, y),继续标记相邻的陆地。

四、关键细节
  • 无需回溯:FloodFill 与回溯不同,格子一旦被标记为已访问,就永久改变状态,不需要撤销。因此递归返回后无需恢复现场。

  • 访问标记的时机 :必须在进入递归前将当前格子标记为已访问,否则会导致重复访问,甚至无限递归。原代码在 dfs 内部未标记起点,这是一个错误。修正方法是在 dfs 开头添加 check[i][j] = true;。

五、流程图讲解

相关推荐
万少7 分钟前
Qoder sonus模型 20分钟,复刻 马斯克 飞天汽车
前端·后端·算法
七牛云行业应用29 分钟前
Muse Spark Open 发布:Meta 称其为美国最强开放权重模型,816B 参数如何落地
算法
esop轻Mes看板亮灯分拣ESD静电安1 小时前
产线“最后一米”的破局密码:ESOP与MES的区别与深度协同
算法
陈天伟教授1 小时前
《数据处理和标注技术》课程能力图谱
人工智能·算法
LMT_Lanmantech1 小时前
HyperWorks许可:almutil显示Unit满了,数据到底准不准?
运维·服务器·算法
禁默1 小时前
论文解读与思考:基于场所地图的标识感知机器人探索方法及工程参考的价值
人工智能·深度学习·算法·机器人
维克兜率天1 小时前
【维克】统计套利建模:从因子到信号的完整流程
android·开发语言·python·算法·kotlin
Zentceh1 小时前
PixelClean 这类 AI 降噪算法是怎么工作的?从 RAW 域到 GAN 色彩重建的技术拆解
图像处理·人工智能·科技·算法·计算机视觉·车载系统·智能硬件
用户0390614707191 小时前
无感观测器理论模型(NTSM-SMO-PLL 与 SMO-PLL)
算法
垆边人似月.2 小时前
找出最小的 K 个数
数据结构·c++·算法