题目

image.png
image.png

题解

水只会往两个方向流动,一个是低处,一个是水平处。不同与其他深度遍历,其他的深度遍历都是从数组挨个开始的。而这次需要从数组的四条边往里面深度优先搜索。这是为什么?小岛里的水想要流向大海,那吗小岛内就需要有个高点,这样水才能向下流,找这个点很难,但是它最后的出水口肯定在岛的四周,也就是数组的四条边。我们假设从岛的四周一点点探寻,寻找能所有能流进太平洋与能流进大西洋的路线,当路线上点重合的时候就是既能流进太平洋又能流进大西洋的路线,这也是我们要找的答案,就像是顺藤摸瓜,从岛的四周开始往岛内部探索

  1. /**
  2. * @param {number[][]} heights
  3. * @return {number[][]}
  4. */
  5. var pacificAtlantic = function (heights) {
  6. // 行的宽度
  7. const rLen = heights.length;
  8. // 列的宽度
  9. const cLen = heights[0].length;
  10. // 矩阵,与给定的数组相对应,当某一项为true说明能流进太平洋
  11. let canReachP = new Array(rLen);
  12. // 矩阵,与给定的数组相对应,当某一项为true说明能流进大西洋
  13. let canReachA = new Array(rLen);
  14. // 为矩阵添加初始值, 每一项的初始值都是false
  15. for(let r = 0; r < rLen; r++) {
  16. canReachA[r] = new Array(cLen).fill(false);
  17. canReachP[r] = new Array(cLen).fill(false);
  18. }
  19. // 存放结果的数组
  20. const result = [];
  21. // dfs
  22. const dfs = (canReachArr, row, col) => {
  23. // 水流的方向
  24. const direction = [-1, 0, 1, 0, -1];
  25. // 当为true 说明水流经过这里
  26. if(canReachArr[row][col]) {
  27. return;
  28. }
  29. // 将对应的矩阵的对应点改为true 说明水流过这里
  30. canReachArr[row][col] = true;
  31. // 水流的下一个位置
  32. for(let i = 0; i < 4; i++) {
  33. let x = row + direction[i];
  34. let y = col + direction[i + 1];
  35. if(x >= 0 && x < rLen && y >= 0 && y < cLen && heights[row][col] <= heights[x][y]) {
  36. dfs(canReachArr, x, y)
  37. }
  38. }
  39. }
  40. // 水想从小岛流出来,那吗岸边会是小岛最低处
  41. // 从小岛最左面和最右面开始寻找上游的终点
  42. for(let r = 0; r < rLen; r++) {
  43. dfs(canReachP, r, 0);
  44. dfs(canReachA, r, cLen - 1);
  45. }
  46. // 从小岛最下面和最上面寻找上游的的终点
  47. for(let c = 0; c < cLen ; c++) {
  48. dfs(canReachA, rLen - 1, c);
  49. dfs(canReachP, 0, c);
  50. }
  51. // 找到那些流向太平洋与大西洋的水流的共同点
  52. for(let r = 0; r < rLen; r++) {
  53. for (let c = 0; c < cLen; c++) {
  54. if (canReachA[r][c] && canReachP[r][c]) {
  55. result.push([r, c]);
  56. }
  57. }
  58. }
  59. return result
  60. };