太平洋大西洋水流问题
难度:
标签:
题目描述
有一个 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
代码结果
运行时间: 73 ms, 内存: 17.5 MB
/*
* Solution in Java using Streams
* This implementation is similar to the regular Java solution, but makes use of Java Stream API for readability.
* The core logic is still based on DFS to mark reachable cells.
*/
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Solution {
public List<int[]> pacificAtlantic(int[][] heights) {
int m = heights.length, n = heights[0].length;
boolean[][] pacific = new boolean[m][n];
boolean[][] atlantic = new boolean[m][n];
IntStream.range(0, m).forEach(i -> {
dfs(heights, pacific, i, 0);
dfs(heights, atlantic, i, n - 1);
});
IntStream.range(0, n).forEach(j -> {
dfs(heights, pacific, 0, j);
dfs(heights, atlantic, m - 1, j);
});
return IntStream.range(0, m)
.boxed()
.flatMap(i -> IntStream.range(0, n)
.filter(j -> pacific[i][j] && atlantic[i][j])
.mapToObj(j -> new int[]{i, j}))
.collect(Collectors.toList());
}
private void dfs(int[][] heights, boolean[][] ocean, int i, int j) {
int m = heights.length, n = heights[0].length;
ocean[i][j] = true;
int[][] directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
for (int[] dir : directions) {
int x = i + dir[0], y = j + dir[1];
if (x >= 0 && x < m && y >= 0 && y < n && !ocean[x][y] && heights[x][y] >= heights[i][j]) {
dfs(heights, ocean, x, y);
}
}
}
}
解释
方法:
该题解采用逆向思维的方式。水从高处往低处流,那么可以从太平洋和大西洋的沿岸点开始向内搜寻,找到比自己高的点,逆流而上。对于每个海洋,分别从行和列的边界开始深度优先搜索,标记能够到达该海洋的点。最后找到既能流到太平洋又能流到大西洋的点,即为满足要求的结果。
时间复杂度:
O(mn)
空间复杂度:
O(mn)
代码细节讲解
🦆
为什么在深度优先搜索(DFS)中,选择从海洋边缘的单元格开始搜索而不是从内陆开始?
▷🦆
在深度优先搜索中,标记过程中为何只考虑与当前单元格高度相等或更高的相邻单元格?
▷🦆
当在DFS中检查一个单元格是否已访问时,如果已访问单元格的高度小于当前单元格,是否应重新访问以模拟更多的水流路径?
▷🦆
在题解中提到的递归深度是`min(m, n)`,这是怎么得出的?在最坏情况下递归深度是否可能更大?
▷