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]]
提示:
m == heights.length
n == heights[r].length
1 <= m, n <= 200
0 <= heights[r][c] <= 105
思路:这是经典的dfs题目,想要一下子找到同时能流进两个海洋的结点有点难,所以可以用两次dfs,分别找到能流入各自海洋的结点,再找重合部分的结点,dfs从边界的结点开始,往四个方向遍历,其余结点如果可以通过该结点流入海洋就让vis数组对应位置设置为true,注意判断边界条件,最后用一个嵌套List存储结果就行
class Solution {
int[][] dir = {{0,1},{0,-1},{-1,0},{1,0}};//定义四个方向
int m,n;
public List<List<Integer>> pacificAtlantic(int[][] heights) {
m = heights.length;
n = heights[0].length;
boolean[][] visp = new boolean[m][n];//标记能流入太平洋的结点
boolean[][] visa = new boolean[m][n];//标记能流入大西洋的结点
//两次dfs
for(int i=0;i<m;i++){
dfs(i,0,visp,heights);//遍历左边靠近太平洋的结点
dfs(i,n-1,visa,heights);//遍历右边靠近大西洋的结点
}
for(int i=0;i<n;i++){
dfs(0,i,visp,heights);//遍历上边靠近太平洋的结点
dfs(m-1,i,visa,heights);//遍历下边靠近大西洋的结点
}
List<List<Integer>> res = new ArrayList<>();
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(visp[i][j] && visa[i][j]){ //同时可以流进太平洋和大西洋的结点
List<Integer> list = new ArrayList<>();
list.add(i);
list.add(j);
res.add(list);
}
}
}
return res;
}
public void dfs(int x,int y,boolean[][] vis,int[][] heights){
vis[x][y] = true;//当前结点可以流进海洋
for(int i=0;i<4;i++){ //向四个方向遍历
int xx = x+dir[i][0];
int yy = y+dir[i][1];
//越界情况或者已经遍历过或者下一个结点小于当前结点无法通过该结点流入海洋
if(xx<0 || xx==m || yy<0 || yy==n || vis[xx][yy] || heights[xx][yy]<heights[x][y]){
continue;
}
dfs(xx,yy,vis,heights);
}
}
}