【LeetCode】417. Pacific Atlantic Water Flow 太平洋大西洋水流问题

1033 篇文章 56 订阅

作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/


题目地址: https://leetcode.com/problems/pacific-atlantic-water-flow/description/

题目描述

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:

在这里插入图片描述

Return:

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

题目大意

上面一条边和左边一条边代表的是太平洋,右边一条边和下边一条边代表的是大西洋。

现在告诉你水往低处流,问哪些位置的水能同时流进太平洋和大西洋?

解题方法

要解决的问题:哪些位置的雨水能同时流进太平洋和大西洋。
重要思路:将水的流向反转,假设太平洋和大西洋的水 从低向高 “攀登”,分别能到达哪些位置,分别用 p_visiteda_visited 表示。两者的交集就代表能同时流向太平洋和大西洋的位置

417. 太平洋大西洋水流问题.001.png
417. 太平洋大西洋水流问题.002.png
417. 太平洋大西洋水流问题.003.png

DFS

直接DFS求解。一般来说 DFS 需要有固定的起点,但是对于本题,4 条边都是能与大洋接壤的,那么就把 4条边界的每个位置都算作 DFS 的起点

使用两个二维数组 p_visiteda_visited,分别记录太平洋和大西洋的水能从低向高“攀登”到的位置。

然后对 4 条边进行遍历,看以这些边的每个位置为起点,进行攀登;把能到达的哪些的位置,分别在 p_visiteda_visited标记出来。

注意了,因为是从边界向中间去“攀登”,所以,这个时候是新的点要比当前的点海拔高才行。

Python代码如下:

class Solution(object):
    def pacificAtlantic(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[List[int]]
        """
        if not matrix or not matrix[0]: return []
        m, n = len(matrix), len(matrix[0])
        p_visited = [[False] * n for _ in range(m)]
        a_visited = [[False] * n for _ in range(m)]
        for i in range(m):
            self.dfs(p_visited, matrix, m, n, i, 0)
            self.dfs(a_visited, matrix, m, n, i, n -1)
        for j in range(n):
            self.dfs(p_visited, matrix, m, n, 0, j)
            self.dfs(a_visited, matrix, m, n, m - 1, j)
        res = []
        for i in range(m):
            for j in range(n):
                if p_visited[i][j] and a_visited[i][j]:
                    res.append([i, j])
        return res
        
    def dfs(self, visited, matrix, m, n, i, j):
        visited[i][j] = True
        directions = [(-1, 0), (1, 0), (0, 1), (0, -1)]
        for dire in directions:
            x, y = i + dire[0], j + dire[1]
            if x < 0 or x >= m or y < 0 or y >= n or visited[x][y] or matrix[x][y] < matrix[i][j]:
                continue
            self.dfs(visited, matrix, m, n, x, y)

C++代码如下:

class Solution {
public:
    vector<pair<int, int>> pacificAtlantic(vector<vector<int>>& matrix) {
        if (matrix.empty() || matrix[0].empty()) return {};
        const int M = matrix.size();
        const int N = matrix[0].size();
        vector<vector<bool>> p_visited(M, vector<bool>(N));
        vector<vector<bool>> a_visited(M, vector<bool>(N));
        for (int i = 0; i < M; ++i) {
            dfs(matrix, p_visited, i, 0);
            dfs(matrix, a_visited, i, N - 1);
        }
        for (int j = 0; j < N; ++j) {
            dfs(matrix, p_visited, 0, j);
            dfs(matrix, a_visited, M - 1, j);
        }
        vector<pair<int, int>> res;
        for (int i = 0; i < M; ++i) {
            for (int j = 0; j < N; ++j) {
                if (p_visited[i][j] && a_visited[i][j]) {
                    res.push_back({i, j});
                }
            }
        }
        return res;
    }
    void dfs(vector<vector<int>>& matrix, vector<vector<bool>>& visited, int i, int j) {
        const int M = matrix.size();
        const int N = matrix[0].size();
        visited[i][j] = true;
        vector<pair<int, int>> dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
        for (auto d : dirs) {
            int nx = i + d.first;
            int ny = j + d.second;
            if (nx >= 0 && nx < M && ny >= 0 && ny < N && !visited[nx][ny] && matrix[nx][ny] >= matrix[i][j]) {
                dfs(matrix, visited, nx, ny);
            }
        }
    }
};

最坏情况下的时间复杂度: O ( ( M + N ) ∗ M N ) O((M+N)*MN) O((M+N)MN)
空间复杂度: O ( M N ) O(MN) O(MN)

参考资料:

https://leetcode.com/problems/pacific-atlantic-water-flow/discuss/90739/Python-DFS-bests-85.-Tips-for-all-DFS-in-matrix-question./181815

总结

  1. DFS 的变化。

日期

2018 年 10 月 1 日 —— 欢度国庆!

  • 0
    点赞
  • 1
    收藏
  • 打赏
    打赏
  • 3
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:猿与汪的秘密 设计师:我叫白小胖 返回首页
评论 3

打赏作者

负雪明烛

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值