开启我的LeetCode刷题日记:417. 太平洋大西洋水流问题

108 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情

编程世界总是离不了算法

最近在看框架源码时,会有很多算法的实现逻辑,有时候会感到吃力

于是决定蹭着假期,加强算法和数据结构相关的知识

那怎么提升呢?

其实我知道算法这东西没有捷径,多写多练才能提升,于是我开启我的LeetCode刷题之旅

第一阶段目标是:200道,每天12

为了不乱,本系列文章目录分为三部分:

  1. 今日题目:xxx
  2. 我的思路
  3. 代码实现

今日题目:417. 太平洋大西洋水流问题

有一个 m × n 的矩形岛屿,与 太平洋 和 大西洋 相邻。 “太平洋” 处于大陆的左边界和上边界,而 “大西洋” 处于大陆的右边界和下边界。

这个岛被分割成一个由若干方形单元格组成的网格。给定一个 m x n 的整数矩阵 heights , heights[r][c] 表示坐标 (r, c) 上单元格 高于海平面的高度 。

岛上雨水较多,如果相邻单元格的高度 小于或等于 当前单元格的高度,雨水可以直接向北、南、东、西流向相邻单元格。水可以从海洋附近的任何单元格流入海洋。

返回网格坐标 result 的 2D 列表 ,其中 result[i] = [ri, ci] 表示雨水从单元格 (ri, ci) 流动 既可流向太平洋也可流向大西洋 。

 

示例 1:

输入: heights = [[1,2,2,3,5],[3,2,3,4,4],[2,4,5,3,1],[6,7,1,4,5],[5,1,1,2,4]] 输出: [[0,4],[1,3],[1,4],[2,2],[3,0],[3,1],[4,0]]

示例 2:

输入: heights = [[2,1],[1,2]] 输出: [[0,0],[0,1],[1,0],[1,1]]  

提示:

m == heights.length n == heights[r].length 1 <= m, n <= 200 0 <= heights[r][c] <= 105

来源:力扣(LeetCode) 链接:leetcode.cn/problems/pa… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我的思路

  1. 倒序推导(逆流而上)。为什么呢?试想一下,如果采用正序,我们需要对每个来源(本题里即每个节点)做DFS,看它是福符合要求。如果采用倒序的话,我们只要从结果开始往上溯源。在本题里,结果是四条边。明显,结果数量远小于来源。
  2. 使用两个矩阵记录结果。我们在做DFS时对每个标记过的节点记录,然后标记过的节点有些是不符合条件的。所以我们需要两个矩阵。一个记录从太平洋到大西洋,一个记录大西洋到太平洋,最后这两个矩阵里重合的点就是符合我们要求的。

代码实现

var pacificAtlantic = function(matrix) {
    if(!matrix || !matrix[0]) { return []; }
    const m = matrix.length;
    const n = matrix[0].length;
    const flow1 = Array.from({ length: m }, () => new Array(n).fill(false));
    const flow2 = Array.from({ length: m }, () => new Array(n).fill(false));
    
    const dfs = (r, c, flow) => {
        flow[r][c] = true;
        [[r-1, c], [r+1, c], [r, c-1], [r, c+1]].forEach(([nr, nc]) => {
            if(
                // 保证在矩阵中
                nr >= 0 && nr < m &&
                nc >= 0 && nc < n &&
                // 防止死循环
                !flow[nr][nc] &&
                // 保证逆流而上
                matrix[nr][nc] >= matrix[r][c]
            ) {
                dfs(nr, nc, flow)
            }
        })
    }
    // 沿着海岸线逆流而上
    for(let r = 0; r<m; r+=1) {
        dfs(r, 0, flow1);
        dfs(r, n-1, flow2)
    }
    for(let c = 0; c <n; c += 1) {
        dfs(0, c, flow1);
        dfs(m-1, c, flow2)
    }
    // 收集能流到两个大洋里的坐标
    const res = []
    for(let r = 0; r < m; r += 1) {
        for(let c = 0; c < n; c += 1) {
            if(flow1[r][c] && flow2[r][c]) {
                res.push([r, c])
            }
        }
    }
    return res;
};

总结

实现方式其实有很多,这里仅供参考~

由于刚开始刷题,也不知道从哪里刷好,如果前辈们有好的建议,希望不吝赐教,感谢🌹