《LeetCode 417 太平洋大西洋水流问题 FloodFill DFS 解法》

一.题目

417. 太平洋大西洋水流问题 - 力扣(LeetCode)

二.思路讲解

2.1 审题

本题要求找出矩阵中所有能够同时流向太平洋和大西洋 的格子。水可以从一个格子流向上下左右 相邻的格子,条件是相邻格子的高度 ≤ 当前格子的高度 。太平洋位于矩阵的上边界和左边界 ,大西洋位于下边界和右边界

2.2 思路讲解

直接判断每个格子是否能同时流向两个海洋比较困难,但可以采用正难则反 的思路:从海洋出发,反向标记能流到海洋的格子。具体做法:

  • 从太平洋边界(上、左)出发,反向进行深度优先搜索(DFS),标记所有能流到太平洋的格子。反向搜索时,水可以从低处流向高处,即相邻格子高度 ≥ 当前格子高度时才能流动。

  • 从大西洋边界(下、右)出发,同样反向搜索,标记所有能流到大西洋的格子。

  • 最后,同时被两个海洋标记的格子就是既能流向太平洋又能流向大西洋的格子。

三.代码演示

cpp 复制代码
class Solution 
{
public:
    int row,col;
    int bx[4] = {0,0,1,-1};
    int by[4] = {1,-1,0,0};
    vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights)
    {
        row = heights.size();col = heights[0].size();
        vector<vector<bool>>Pac(row,vector<bool>(col));
        vector<vector<bool>>Atl(row,vector<bool>(col));
        //处理太平洋
        for(int j = 0;j < col;j++) dfs(heights,0,j,Pac);
        for(int i = 0;i < row;i++) dfs(heights,i,0,Pac);
        //处理大西洋
        for(int i = 0;i < row;i++) dfs(heights,i,col - 1,Atl);
        for(int j = 0;j < col;j++) dfs(heights,row - 1,j,Atl);
        //处理二者相交部分
        vector<vector<int>> ret;
        for(int i = 0;i < row;i++)
        {
            for(int j = 0;j < col;j++)
            {
                if(Pac[i][j] && Atl[i][j])
                {
                    ret.push_back({i,j});
                }
            }
        }
        return ret;
    }
    void dfs(vector<vector<int>>& heights,int i,int j,vector<vector<bool>>& cur)
    {
        cur[i][j] = true;
        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 && !cur[x][y] && heights[i][j] <= heights[x][y])
            {
                dfs(heights,x,y,cur);
            }
        }
    }
};

四.代码讲解

一、全局变量与方向数组
  • rowcol:成员变量,存储网格的行数和列数。

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

二、主函数 pacificAtlantic
  1. 获取网格尺寸row = heights.size(); col = heights[0].size();

  2. 初始化两个布尔矩阵

    • Pac:记录能流到太平洋的格子,初始全 false

    • Atl:记录能流到大西洋的格子,初始全 false

  3. 从太平洋边界出发进行反向DFS

    • 遍历第一行(i = 0)的所有列,调用 dfs(heights, 0, j, Pac)

    • 遍历第一列(j = 0)的所有行,调用 dfs(heights, i, 0, Pac)

    • 注意:左上角格子 (0,0) 会被调用两次,但 dfs 内会检查 cur[i][j],已访问则直接返回,不会重复。

  4. 从大西洋边界出发进行反向DFS

    • 遍历最后一行(i = row-1)的所有列,调用 dfs(heights, i, col-1, Atl)

    • 遍历最后一列(j = col-1)的所有行,调用 dfs(heights, row-1, j, Atl)

  5. 收集既能流向太平洋又能流向大西洋的格子

    • 遍历整个网格,如果 Pac[i][j]Atl[i][j] 都为 true,则将坐标 {i, j} 加入结果集。

    • 返回结果集。

三、递归函数 dfs

dfs(heights, i, j, cur) 从格子 (i, j) 开始,反向标记所有能流到当前海洋的格子。执行流程:

  1. 标记当前格子cur[i][j] = true,表示该格子能流向对应的海洋。

  2. 向四个方向探索 :遍历四个方向,计算新坐标 (x, y)

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

    • 未访问!cur[x][y]

    • 反向流动条件heights[i][j] <= heights[x][y]

      • 正向水从高处流向低处(h_current >= h_neighbor)。

      • 反向搜索时,如果邻居的高度 大于等于 当前格子,则水可以从邻居流向当前格子,因此当前格子能流向海洋 → 邻居也能流向海洋。

  3. 若满足条件,则递归调用 dfs(heights, x, y, cur),继续标记。

四、关键细节
  • 反向搜索的条件heights[i][j] <= heights[x][y] 确保从低处向高处搜索,这与正向水流方向相反,但正是标记能流到海洋的格子的正确方式。

  • 标记数组重用PacAtl 既是访问标记,也是最终结果标记,节省空间。

  • 避免重复访问 :在递归入口先检查 cur[i][j],但代码中是在递归调用时用 !cur[x][y] 判断,而当前格子已在进入时标记,因此不会重复。

五、流程图

相关推荐
凌波粒1 小时前
LeetCode--46.全排列(回溯算法)
数据结构·算法·leetcode
鱼子星_1 小时前
C++从零开始系列篇(二):C++入门——函数重载,引用,inline与nullptr
开发语言·c++·笔记
2zcode1 小时前
项目文档:基于MATLAB语音信号变声算法设计与实现
算法·matlab·语音识别
指令集梦境1 小时前
图解:单调栈算法模板(Java语言)
java·开发语言·算法
小灰灰搞电子2 小时前
C++ boost::circular_buffer 详解:原理、用法与实战
开发语言·c++·boost
生成论实验室2 小时前
自动驾驶:一个自主运动的系统
人工智能·算法·机器学习·语言模型·机器人·自动驾驶·安全架构
sheeta19982 小时前
LeetCode 每日一题笔记 日期:2026.06.16 题目:3612. 字符串特殊符号处理
笔记·算法·leetcode
青山木2 小时前
Hot 100 --- 矩阵置零
线性代数·算法·leetcode·矩阵·哈希算法
Jasmine_llq2 小时前
《B4264 [GESP202503 四级] 二阶矩阵》
线性代数·算法·矩阵·二维矩阵遍历枚举所有2×2矩阵·交叉乘积等式条件判断·输入输出快读加速·长整型防溢出计数统计