力扣解题思路:417. 太平洋大西洋水流问题

417. 太平洋大西洋水流问题


思路:题目:

Given the following 5x5 matrix:

  Pacific ~   ~   ~   ~   ~
       ~  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  *
          *   *   *   *   * Atlantic

Return:
[[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]] (positions with parentheses in above matrix).

左边和上边是太平洋,右边和下边是大西洋,内部的数字代表海拔,海拔高的地方的水能够流到低的地方,求解水能够流到太平洋和大西洋的所有位置。
显然这种题目用DFS或者BFS都是可以的,这并不是求最短路径的问题,并且DFS可以使代码更加简洁清晰,所以我们使用DFS来解题。->
这一题的难点不在于如何进行递归,如果矩阵的四周都是大西洋或者太平洋就好说,但是消灾的情况并不是这样,我们要求的是水能够流到太平洋和大西洋的所有位置。所以我们要用两个boolean矩阵分别记录能流向大西洋和太平洋的左边取“与”即可。->
由于只有最高点才可能成为所求点,从最高点往周围遍历显然没有直接从四周往中间遍历来得清晰(因为四周的点数更少):

int m = matrix.length;
if(m < 1) return ret;
int n = matrix[0].length;
boolean[][] Pacific = new boolean[m][n];
boolean[][] Atlantic = new boolean[m][n];
for(int i = 0; i < m; ++i) {
    dfs(matrix, i, 0, Pacific, matrix[i][0]);
    dfs(matrix, i, n-1, Atlantic, matrix[i][n-1]);
}
for(int i = 0; i < n; ++i) {
    dfs(matrix, 0, i, Pacific, matrix[0][i]);
    dfs(matrix, m-1, i, Atlantic, matrix[m-1][i]); 
}

接下来来构造DFS递归函数,首先我们需要确定递归函数的出口,即超出边界或者已访问过,或者不满足水的流向条件:

if(x < 0 || y < 0 || x >= m.length || y >= m[0].length || visited[x][y] || m[x][y] < pre) 
    return;

接下来向四周进行递归,并将visited置为已访问:

visited[x][y] = true;
dfs(m, x+1, y, visited, m[x][y]);
dfs(m, x-1, y, visited, m[x][y]);
dfs(m, x, y+1, visited, m[x][y]);
dfs(m, x, y-1, visited, m[x][y]);

最后完整的遍历一遍数组,满足Pacific[i][j] && Atlantic[i][j]的即为所求点,将其加入到结果集中,完整代码如下:

public List<List<Integer>> pacificAtlantic(int[][] matrix) {
    List<List<Integer>> ret = new ArrayList<>();
    int m = matrix.length;
    if(m < 1) return ret;
    int n = matrix[0].length;
    boolean[][] Pacific = new boolean[m][n];
    boolean[][] Atlantic = new boolean[m][n];
    for(int i = 0; i < m; ++i) {
        dfs(matrix, i, 0, Pacific, matrix[i][0]);
        dfs(matrix, i, n-1, Atlantic, matrix[i][n-1]);
    }
    for(int i = 0; i < n; ++i) {
        dfs(matrix, 0, i, Pacific, matrix[0][i]);
        dfs(matrix, m-1, i, Atlantic, matrix[m-1][i]); 
    }
    for(int i = 0; i < m; ++i) {
        for(int j = 0; j < n; ++j)
            if(Pacific[i][j] && Atlantic[i][j]){
                List<Integer> list = new ArrayList<>();
                list.add(i);
                list.add(j);
                ret.add(list);
            }
                
    }
    return ret;
}

其中递归函数如下:

public void dfs(int[][] m, int x, int y, boolean[][] visited, int pre) {
    if(x < 0 || y < 0 || x >= m.length || y >= m[0].length || visited[x][y] || m[x][y] < pre) 
        return;
    visited[x][y] = true;
    dfs(m, x+1, y, visited, m[x][y]);
    dfs(m, x-1, y, visited, m[x][y]);
    dfs(m, x, y+1, visited, m[x][y]);
    dfs(m, x, y-1, visited, m[x][y]);
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值