太平洋大西洋水流问题

题目链接

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

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

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

示例:

给定下面的 5x5 矩阵:

  太平洋 ~   ~   ~   ~   ~ 
       ~  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]] (上图中带括号的单元).

思路

解法一:

当下一个点比当前的点大时或者等于当前点的高度时,水才能流过去。根据这个思路,找到可以流向太平洋和大西洋的点。

  1. 找出所有从太平洋出发的水所能达到的点;
  2. 找出所有从大西洋出发的水所能达到的点;
  3. 找出重合的点。
class Solution
{
public:
    vector<vector<int>> P, A, ans;
    int n, m;
    vector<vector<int>> pacificAtlantic(vector<vector<int>> &heights)
    {
        m = heights.size();
        n = heights[0].size();

        P = A = vector<vector<int>>(m, vector<int>(n, 0));

        for (int i = 0; i < m; ++i)
        {
            dfs(heights, P, i, 0);
            dfs(heights, A, i, n - 1);
        }
        for (int j = 0; j < n; ++j)
        {
            dfs(heights, P, 0, j);
            dfs(heights, A, m - 1, j);
        }
        return ans;
    }

    void dfs(vector<vector<int>> &heights, vector<vector<int>> &visited, int i, int j)
    {
        if (visited[i][j]) { // 之前访问过,忽略
            return;
        } 
            
        visited[i][j] = 1;
        if (P[i][j] && A[i][j]) // 均可达
        {
            ans.push_back({i, j});
        }
        //上下左右深搜
        if (i - 1 >= 0 && heights[i - 1][j] >= heights[i][j]) {
            dfs(heights, visited, i - 1, j);
        }

        if (i + 1 < m && heights[i + 1][j] >= heights[i][j]) {
            dfs(heights, visited, i + 1, j);
        }

        if (j - 1 >= 0 && heights[i][j - 1] >= heights[i][j]) {
            dfs(heights, visited, i, j - 1);
        }
            
        if (j + 1 < n && heights[i][j + 1] >= heights[i][j]) {
            dfs(heights, visited, i, j + 1);
        }
            
    }
};