417. 太平洋大西洋水流问题(DFS)


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

题目

给定一个 m x n 的非负整数矩阵来表示一片大陆上各个单元格的高度。“太平洋”处于大陆的左边界和上边界,而“大西洋”处于大陆的右边界和下边界。

规定水流只能按照上、下、左、右四个方向流动,且只能从高到低或者在同等高度上流动。

请找出那些水流既可以流动到“太平洋”,又能流动到“大西洋”的陆地单元的坐标。

提示:

  • 输出坐标的顺序不重要
  • m 和 n 都小于150

在这里插入图片描述

解题思路

这题和130题有点类似,都是从边界往内寻找。

这题呢我们从边界出发,假设先从上边出发,也就是太平洋。 靠近上边的水流一定都可以流入太平洋,那么我们只需要将“上边”遍历,找到高度比它高的,就可以通过它流入太平洋。其它三条边也是这样。只不过右边和下边是可以流入大西洋。

解释一下:题目说高度高的可以向高度低的或者高度相等的流动。 也就是说,只要比上边的水流的高度高,或者相等,那么该水流就可以流到上边,而上边又和太平洋相连,即该水流可流入太平洋。

这样,两轮循环,一轮用来找到可以流入太平洋的水流, 一轮找到可以流入大西洋的水流,把它们分别放入两个boolean数组中,然后再来一次整个数组遍历,如果有一个水流 即可流入太平洋也可流入大西洋(toPa[i][j] && toAt[i][j])。那么它就是我们要寻找的。把它的坐标放入res,返回即可。

本题的重点就是 中间的水流可以通过四条边的水流 流入对应的海洋。

代码

class Solution {
    public List<List<Integer>> pacificAtlantic(int[][] matrix) {
        List<List<Integer>> res = new ArrayList<>();

        if (matrix.length == 0 || matrix[0].length == 0) {
            return res;
        }

        int r = matrix.length;//行数,可以看成y轴
        int c = matrix[0].length;//列数,可以看成x轴
        boolean[][] toPa = new boolean[r][c];
        boolean[][] toAt = new boolean[r][c];

        for (int i = 0; i < r; i++) {//要去选择第一列和最后一列,  变化的是行数,列数是固定的0和c-1,所以这里循环条件用行(r)
            //第一次遍历,会给一个初始高度,到后面要进行比较的时候再用matrix[r][c] 来替换初始高度
            DFS(i, 0, matrix, toPa, Integer.MIN_VALUE);//遍历第一列  即正方形的左边,它用DFS来遍历哪些能够通过它 ,到达太平洋(Pa)的水流。下面的同理
            DFS(i, c - 1, matrix, toAt, Integer.MIN_VALUE);//遍历最后一列
        }

        for (int i = 0; i < c; i++) {
            DFS(0, i, matrix, toPa, Integer.MIN_VALUE);//遍历第一行
            DFS(r - 1, i, matrix, toAt, Integer.MIN_VALUE);//遍历最后一行
        }

        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {//遍历整个二维数组
                if (toPa[i][j] && toAt[i][j]) {//如果该水流即能到达pa也能到达at,就是我们的目标
                    List<Integer> cur = new ArrayList<>();
                    cur.add(i);
                    cur.add(j);
                    res.add(cur);
                }
            }
        }
        return res;
    }

    int[][] directions = new int[][]{{0, 1}, {0, -1}, {-1, 0}, {1, 0}};

    public void DFS(int r, int c, int[][] matrix, boolean[][] toSea, int height) {
        if (r < 0 || r >= matrix.length
                || c < 0 || c >= matrix[0].length
                || toSea[r][c]
                || matrix[r][c] < height) {//matrix[r][c] < height即现在遍历到的水流高度,比之前那个要小,这是不可以的,因为只有现在的高度大于之前的高度,才可以通过之前的流入海洋
            return;
        }
        toSea[r][c] = true;//它能够到达大西洋或者太平洋。要根据具体是那个在那个循环调用的。
        for (int[] dir : directions) {
            /*
            r + dir[0]:相当于横坐标向四个方向遍历
            c + dir[1]:相当于纵坐标向四个方向遍历
             */
            DFS(r + dir[0], c + dir[1], matrix, toSea, matrix[r][c]);//这时候高度就会更新为matrix[r][c]
        }

    }
}

文章作者: fFee-ops
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 fFee-ops !
评论
  目录