一、题目
有一个 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
二、思路
- 把矩阵想象成图
- 从海岸线逆流而上遍历图,所到之处就是可以流到某个大洋的坐标
具体步骤
- 新建两个矩阵,分别记录能流到两个大洋的坐标
- 从海岸线,多管齐下,同时深度优先遍历图,过程中填充上述矩阵
- 遍历两个矩阵,找出能流到两个大洋的坐标
三、题解
/**
* @param {number[][]} heights
* @return {number[][]}
*/
var pacificAtlantic = function (heights) {
if (!heights || !heights[0]) { return []; }
const m = heights.length
const n = heights[0].length
const flow1 = Array.from({ length: m }, () => new Array(n).fill(false))
const flow2 = Array.from({ length: m }, () => new Array(n).fill(false))
// r:row, c:column
const dfs = (r, c, flow) => {
flow[r][c] = true
const nextArr = [[r - 1, c], [r + 1, c], [r, c - 1], [r, c + 1]]
nextArr.forEach(([nr, nc]) => {
if (
// 保证在矩阵中
nr >= 0 && nr < m &&
nc >= 0 && nc < n &&
// 防止死循环
!flow[nr][nc] &&
// 保证逆流而上
heights[nr][nc] >= heights[r][c]
) {
dfs(nr, nc, flow)
}
})
}
// 沿着四条海岸线逆流而上
for (let r = 0; r < m; r++) {
dfs(r, 0, flow1)
dfs(r, n - 1, flow2)
}
for (let c = 0; c < n; c++) {
dfs(0, c, flow1)
dfs(m - 1, c, flow2)
}
// 收集能流到两个大洋里的坐标
const res = []
for (let r = 0; r < m; r++) {
for (let c = 0; c < n; c++) {
if (flow1[r][c] && flow2[r][c]) {
res.push([r, c])
}
}
}
return res;
};
复杂度分析
- 时间复杂度:O(m*n)
- 空间复杂度:O(m*n)