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

 

☆☆☆思路:类似于130题。从边界开始扩展。

  建立两个矩阵Atlantic和Pacific, 当Atlantic[i][j]和Pacific[i][j]同时为true时表示该位置可以同时到达Atlantic和Pacific

  遍历时的技巧为: 只需要从四个边界开始遍历即可(类似Flood Fill的思想, 只要可以从边界出发到达, 就说明该位置的水可以流向对应的海洋)

class Solution {
    public List<List<Integer>> pacificAtlantic(int[][] matrix) {
        List<List<Integer>> res = new ArrayList<>();
        if (matrix == null || matrix.length == 0) return res;
        int m = matrix.length, 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]); //
            dfs1(matrix, i, 0, pacific); //
            dfs1(matrix, i, n-1, atlantic); //
        }
        // 第一行 和 最后一行
        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]); //
            dfs1(matrix, 0, i, pacific); //
            dfs1(matrix, m-1, i, atlantic); //
        }
        // 当atlantic和pacific同时为true时表示该位置可以同时到达Atlantic和Pacific
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (pacific[i][j] && atlantic[i][j]) {
                    res.add(Arrays.asList(i, j));
                }
            }
        }
        return res;
    }
    // FloodFill算法 —— 写法1, 需要记录前一个值pre
    private void dfs(int[][] matrix, int x, int y, boolean[][] visited, int pre) {
        // 越界判断 以及 是否访问过 判断
        if (x < 0 || x >= matrix.length || y < 0 || y >= matrix[0].length || visited[x][y]) return;
        if (matrix[x][y] < pre) return; // 必须逆流而上
        visited[x][y] = true;
        dfs(matrix, x - 1, y, visited, matrix[x][y]);
        dfs(matrix, x, y + 1, visited, matrix[x][y]);
        dfs(matrix, x + 1, y, visited, matrix[x][y]);
        dfs(matrix, x, y - 1, visited, matrix[x][y]);
    }

    // FloodFill算法 —— 写法2
    int[][] d = new int[][]{ {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; // 方向顺序不重要
    private boolean isArea(int[][] matrix, int x, int y) {
        return x >= 0 && x < matrix.length && y >= 0 && y < matrix[0].length;
    }
    private void dfs1(int[][] matrix, int x, int y, boolean[][] visited) {
        visited[x][y] = true;
        for (int i = 0; i < 4; i++) {
            int newx = x + d[i][0];
            int newy = y + d[i][1];
            if (isArea(matrix, newx, newy) && !visited[newx][newy] && matrix[newx][newy] >= matrix[x][y]) {
                dfs1(matrix, newx, newy, visited);
            }
        }
    }
}

 

posted @ 2020-12-29 17:18  不学无墅_NKer  阅读(117)  评论(0编辑  收藏  举报