zoukankan      html  css  js  c++  java
  • [LeetCode] 417. Pacific Atlantic Water Flow

    Given an m x n matrix of non-negative integers representing the height of each unit cell in a continent, the "Pacific ocean" touches the left and top edges of the matrix and the "Atlantic ocean" touches the right and bottom edges.

    Water can only flow in four directions (up, down, left, or right) from a cell to another one with height equal or lower.

    Find the list of grid coordinates where water can flow to both the Pacific and Atlantic ocean.

    Note:

    1. The order of returned grid coordinates does not matter.
    2. Both m and n are less than 150.

    Example:

    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).

    太平洋大西洋水流问题。给一个二维矩阵,矩阵里的数字表示水的高度。矩阵的边缘是太平洋和大西洋。水流遵循高处往低处流的原则,求这个矩阵里面哪些坐标上的水能同时流动到太平洋和大西洋。例子中所有带括号的坐标,最终都能流向两个海洋。

    这一题也属于flood fill类的题目。但是这个题的做法非常巧妙,可以试着从矩阵的边缘往中间找,看看最远能找到矩阵内的哪些坐标。这些被找到的坐标上的水一定能流到两个海洋里。比如左边缘和上边缘是太平洋,就可以找i == 0和j == 0的坐标去做DFS,并记录有哪些坐标能被遍历到。同理,右边缘和下边缘是大西洋,可以找i == m  - 1和j == n - 1的坐标去做DFS,并记录哪些坐标能被找到。在两次DFS中都被找到的坐标,则是可以同时流向两个大洋的。

    同时这一题在做DFS的时候,也跟329题类似,需要记录一个prev值,以判断当前坐标上的水的深度和之前遍历的坐标上的水的深度谁高谁低。

    时间O(mn)

    空间O(mn)

    Java实现

     1 class Solution {
     2     public List<List<Integer>> pacificAtlantic(int[][] matrix) {
     3         List<List<Integer>> res = new ArrayList<>();
     4         // corner case
     5         if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
     6             return res;
     7         }
     8 
     9         // normal case
    10         int m = matrix.length;
    11         int n = matrix[0].length;
    12         int[][] pacific = new int[m][n];
    13         int[][] atlantic = new int[m][n];
    14         // scan the edge
    15         for (int i = 0; i < m; i++) {
    16             for (int j = 0; j < n; j++) {
    17                 if (i == 0 || j == 0) {
    18                     dfs(matrix, pacific, i, j, matrix[i][j]);
    19                 }
    20                 if (i == m - 1 || j == n - 1) {
    21                     dfs(matrix, atlantic, i, j, matrix[i][j]);
    22                 }
    23             }
    24         }
    25 
    26         // the rest of the matrix
    27         for (int i = 0; i < m; i++) {
    28             for (int j = 0; j < n; j++) {
    29                 if (pacific[i][j] == 1 && atlantic[i][j] == 1) {
    30                     res.add(Arrays.asList(i, j));
    31                 }
    32             }
    33         }
    34         return res;
    35     }
    36 
    37     private void dfs(int[][] matrix, int[][] visited, int i, int j, int prevHeight) {
    38         // corner case
    39         if (i < 0 || j < 0 || i >= matrix.length || j >= matrix[0].length || visited[i][j] == 1
    40                 || matrix[i][j] < prevHeight) {
    41             return;
    42         }
    43         visited[i][j] = 1;
    44         dfs(matrix, visited, i - 1, j, matrix[i][j]);
    45         dfs(matrix, visited, i + 1, j, matrix[i][j]);
    46         dfs(matrix, visited, i, j - 1, matrix[i][j]);
    47         dfs(matrix, visited, i, j + 1, matrix[i][j]);
    48     }
    49 }

    flood fill题型总结

    LeetCode 题目总结

  • 相关阅读:
    程序运行时被用户删除了工作目录后崩溃
    const引用与非const引用
    NDKr10的各种BUG
    《区块链100问》第64集:区块链分叉是什么?
    《区块链100问》第65集:比特币生孩子了
    《区块链100问》第66集:软分叉和硬分叉是什么?
    《区块链100问》第67集:重放攻击是什么?
    《区块链100问》第68集:硬分叉之以太经典
    《区块链100问》第69集:区块链项目的分类和应用
    《区块链100问》第70集:区块链项目之币类
  • 原文地址:https://www.cnblogs.com/cnoodle/p/13364154.html
Copyright © 2011-2022 走看看