《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);
            }
        }
    }
};

四.代码讲解

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

  • 方向数组 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] 确保从低处向高处搜索,这与正向水流方向相反,但正是标记能流到海洋的格子的正确方式。

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

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

五、流程图

相关推荐
Fruit_Caller4 小时前
static
开发语言·c++
用户979984807189 小时前
200 行代码写一个能跑的 AI Agent:不依赖任何框架,只靠 tool-calling 原理
算法
threerocks9 小时前
【Muse实战】X 流量作战室搭建保姆级教程 - 拥有你自己的运营团队
算法
GreenTea9 小时前
深度拆解 ScienceBuddy:如何用“双层递归自进化”构建高可靠科研 Agent Harness
前端·后端·算法
花椒技术10 小时前
2.46 秒生成 5 秒视频:拆解 H3 Max 的模型、推理栈与硬件协同
算法·音视频开发·视频编码
vivo互联网技术10 小时前
ART:妆容迁移框架,重新定义高保真妆容迁移 | ECCV 2026
人工智能·算法·图像识别
用户04414409244910 小时前
卫星信号模拟器里的四个坐标转换公式
算法
橘和柠10 小时前
阿里 open-code-review (AI代码审查工具)实战:安装、四层规则链、自定义规则格式与实测避坑
算法·面试
得物技术10 小时前
别再只卷向量检索了,得物交易搜索如何用“生成式”实现召回范式跃迁?
人工智能·算法·llm
罗西的思考10 小时前
[Agent Memory / 强化学习] MemPO源码学习笔记 ---(4)--- Rollout实现细节
人工智能·算法