616 字
3 分钟
LeetCode-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]]
DFS的解法
思路:
这道题最容易让我们陷入的误区是“正向思维”:遍历每一个格子,分别做 DFS 看它能不能一路走到太平洋和大西洋。这种做法会产生大量重复计算,时间复杂度直接爆炸到 O((M * N)^2)
-
所以我们逆向思维,太平洋和大西洋倒灌,用表记录能到达的地方,最后比较一下即可,思路不是很复杂
-
但是有几个注意点:
- 这个矩阵需要用循环初始化,不然内部的切片没有初始化,无法使用
visited[row][col] - DFS的边界条件注意下,逆着来可能会出错
- 这个矩阵需要用循环初始化,不然内部的切片没有初始化,无法使用
func pacificAtlantic(heights [][]int) [][]int { if len(heights) == 0 || len(heights[0]) == 0 { return nil }
m, n := len(heights), len(heights[0]) pacific := make([][]bool, m) atlantic := make([][]bool, m) for i := 0; i < m; i++ { pacific[i] = make([]bool, n) atlantic[i] = make([]bool, n) }
var dfs func(row, col int, visited [][]bool, pre int) dfs = func(row, col int, visited [][]bool, pre int) { if row < 0 || col < 0 || row >= m || col >= n || visited[row][col] || heights[row][col] < pre { return }
visited[row][col] = true
dfs(row-1, col, visited, heights[row][col]) dfs(row+1, col, visited, heights[row][col]) dfs(row, col-1, visited, heights[row][col]) dfs(row, col+1, visited, heights[row][col]) }
for i := 0; i < m; i++ { dfs(i, 0, pacific, heights[i][0]) dfs(i, n-1, atlantic, heights[i][n-1]) }
for j := 0; j < n; j++ { dfs(0, j, pacific, heights[0][j]) dfs(m-1, j, atlantic, heights[m-1][j]) }
res := [][]int{} for i:= 0; i < m; i++ { for j := 0; j < n; j++ { if atlantic[i][j] && pacific[i][j] { res = append(res, []int{i, j}) } } }
return res} LeetCode-417.太平洋大西洋水流问题
https://sheep44044.github.io/posts/算法/图论/leetcode-417太平洋大西洋水流问题/