[JavaScript 刷题] 搜索 - 太平洋大西洋水流问题, leetcode 417

Posted GoldenaArcher

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[JavaScript 刷题] 搜索 - 太平洋大西洋水流问题, leetcode 417相关的知识,希望对你有一定的参考价值。

[javascript 刷题] 搜索 - 太平洋大西洋水流问题, leetcode 417

github repo 地址: https://github.com/GoldenaArcher/js_leetcode,Github 的目录 大概 会更新的更勤快一些。

题目地址:417. Pacific Atlantic Water Flow

这个题目真的建议吃透它,也是 Blind Leetcode 75 中的题目之一,是比较核心的内容了。

题目

如下:

There is an m x n rectangular island that borders both the Pacific Ocean and Atlantic Ocean. The Pacific Ocean touches the island’s left and top edges, and the Atlantic Ocean touches the island’s right and bottom edges.

The island is partitioned into a grid of square cells. You are given an m x n integer matrix heights where heights[r][c] represents the height above sea level of the cell at coordinate (r, c).

The island receives a lot of rain, and the rain water can flow to neighboring cells directly north, south, east, and west if the neighboring cell’s height is less than or equal to the current cell’s height. Water can flow from any cell adjacent to an ocean into the ocean.

Return a 2D list of grid coordinates result where result[i] = [ri, ci] denotes that rain water can flow from cell (ri, ci) to both the Pacific and Atlantic oceans.

解题思路

我个人感觉这道题是两个题目的结合+变种:

  • 腐烂的橘子, leetcode 994

    虽然这题用的是 BFS 的解法,不过要考虑 多个起始点 的逻辑在这里

  • 被围绕的区域,leetcode 130

    这题就稍微要开拓一下思路,与其从中间计算可被围绕的区域,不如逆向思维,从边界开始计算不会被围绕的区域。

本题也是一样的逻辑。

刚拿到题的时候,可能第一个想法是:

使用 DFS 找出能够能到达 太平洋大西洋 的点。

但是与 被围绕的区域,leetcode 130 这道题一样,找到这个点会非常的困难,尤其一旦当前路径是无法抵达的路径是,backtracking 的过程会非常的困难。

但是将这道题简化为:

使用 DFS 找到从 太平洋大西洋 方向上所有可抵达的区域

使用 DFS 找到从 大西洋太平洋 方向上所有可抵达的区域

找到两条路径的交集

以题目中的图为例:

从太平洋向大西洋延申的路径:

从太平洋向大西洋延申的路径:

随后寻求出二者的交集即可:

使用 JavaScript 解题

const directions = [
  [1, 0],
  [-1, 0],
  [0, 1],
  [0, -1],
];

const dfs = (visited, grid, row, col, currPos) => 
  const pos = row + "," + col;

  if (visited.has(pos)) return;

  if (row >= grid.length || row < 0 || col >= grid[0].length || col < 0) return;

  if (currPos > grid[row][col]) return;

  visited.add(pos);

  for (const [rc, cc] of directions) 
    dfs(visited, grid, rc + row, cc + col, grid[row][col]);
  
;

/**
 * @param number[][] heights
 * @return number[][]
 */
var pacificAtlantic = function (heights) 
  const pacific = new Set();
  const atalantic = new Set();

  for (let row = 0; row < heights.length; row++) 
    dfs(pacific, heights, row, 0, 0);
    dfs(atalantic, heights, row, heights[0].length - 1, 0);
  

  for (let col = 0; col < heights[0].length; col++) 
    dfs(pacific, heights, 0, col, 0);
    dfs(atalantic, heights, heights.length - 1, col, 0);
  

  const res = [];

  const iterateSet = pacific.size > atalantic.size ? atalantic : pacific;
  const otherSet = pacific.size <= atalantic.size ? atalantic : pacific;

  for (const pos of iterateSet) 
    if (otherSet.has(pos)) 
      const [r, c] = pos.split(",");
      res.push([r, c]);
    
  

  return res;
;

for 循环体中传进去的数值是 0,这是根据题目中来的:

0 <= heights[r][c] <= 10^5

也就是说,海水的数值只要小于等于 0 即可。

保存访问过的路径没有直接保存数组,而是将数组合并成了一个字符串。JavaScript 中的 Set 对数组的追溯是有一定问题的,主要是因为数组是 Object 类型,一旦进行 Object 的比较,就会涉及到引用的问题,如:

虽然 Set 中已经加进去了一个 [1, 2],可是在使用 has 进行判断的时候依旧会返回一个 false。

字符串是 primitive data type,JavaScript 中的基础类型,就不会出现这个问题。最后在解题的时候只要使用 split 去重新还原成一个数组即可。

开发者涨薪指南 48位大咖的思考法则、工作方式、逻辑体系

以上是关于[JavaScript 刷题] 搜索 - 太平洋大西洋水流问题, leetcode 417的主要内容,如果未能解决你的问题,请参考以下文章

[JavaScript 刷题] 搜索 - 单词搜索, leetcode 79

[JavaScript 刷题] 搜索 - 单词搜索, leetcode 79

[JavaScript 刷题] 搜索 - 单词搜索, leetcode 79

[JavaScript 刷题] 二分搜索 - 搜索二维矩阵, leetcode 74

[JavaScript 刷题] 二分搜索 - 搜索二维矩阵, leetcode 74

[JavaScript 刷题] 搜索 - DFS(深度优先搜索)