Leetcode 417. Pacific Atlantic Water Flow(python+cpp)

本文介绍了LeetCode 417题目的解法,通过二刷优化,提出了一种从靠近大洋的边界反向搜索的DFS策略,避免了全数组遍历带来的高复杂度,将复杂度降低到O((M+N)*MN)。并提供了简洁的Python和C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Leetcode 417. Pacific Atlantic Water Flow

题目

在这里插入图片描述
在这里插入图片描述

解析

这道题肯定第一时间想到的是dfs。但是这边如果遍历数组的每个位置进行dfs的话,复杂度太高了,这样做理论上时间复杂度会是O((MN)(M*N))。所以可以采用一种逆向的思路。从靠近大洋的四条边开始反向搜索,反向搜索的过程中把能够到的位置进行标记。如果某个位置两个大洋同时都能到,那么这个位置满足条件。这样的复杂度就是O((M+N)*MN).

二刷解法,更简洁

class Solution:
    def pacificAtlantic(self, heights: List[List[int]]) -> List[List[int]]:
        can_reach_pacific = self.can_reach(heights,'pacific')
        can_reach_atlan = self.can_reach(heights,'atlan')
        ans = []
        for i in range(len(heights)):
            for j in range(len(heights[0])):
                if can_reach_pacific[i][j] and can_reach_atlan[i][j]:
                    ans.append([i,j])
        return ans
                
    def can_reach(self,heights,ocean):
        m,n = len(heights),len(heights[0])
        can_reach = [[False]*n for _ in range(m)]
        visited = [[False]*n for _ in range(m)]
        q = collections.deque()
        if ocean == 'pacific':
            for i in range(m):
                can_reach[i][0] = True
                q.append((i,0))
                visited[i][0] = True
            for i in range(n):
                can_reach[0][i] = True
                q.append((0,i))
                visited[0][i] = True
        else:
            for i in range(m):
                can_reach[i][n-1] = True
                q.append((i,n-1))
                visited[i][n-1] = True
            for i in range(n):
                can_reach[m-1][i] = True
                q.append((m-1,i))
                visited[m-1][i] = True
        
        dirs = [[1,0],[-1,0],[0,1],[0,-1]]
        while q:
            i,j = q.popleft()
            for d in dirs:
                x = i + d[0]
                y = j + d[1]
                if 0 <= x < m and 0 <= y < n and not visited[x][y] and heights[x][y] >= heights[i][j]:
                    q.append((x,y))
                    can_reach[x][y] = True
                    visited[x][y] = True
        return can_reach

python代码:这边不知道咋的复制过来格式一直出错,就截图将就看吧
在这里插入图片描述
当然BFS也是能做的:

class Solution:
    def pacificAtlantic(self, matrix: List[List[int]]) -> List[List[int]]:

        if not matrix or not matrix[0]:
            return []
        
        def helper(ocean,i,j):
            ocean[i][j] = True
            
            q = collections.deque()
            q.append((i,j))
            while q:
                curr_pos = q.popleft()
                dirs = [[0,1],[0,-1],[-1,0],[1,0]]
                for d in dirs:
                    x = curr_pos[0]+d[0]
                    y = curr_pos[1]+d[1]
                
                    if 0<=x<len(ocean) and 0<=y<len(ocean[0]) and matrix[x][y]>=matrix[curr_pos[0]][curr_pos[1]] and not ocean[x][y]:
                        q.append((x,y))
                        ocean[x][y] = True
        
        m = len(matrix)
        n = len(matrix[0])
        
        pacific = [[False]*n for _ in range(m)]
        atlantic = [[False]*n for _ in range(m)]
        
        for i in range(m):
            helper(pacific,i,0)
            helper(atlantic,i,n-1)
        
        for i in range(n):
            helper(pacific,0,i)
            helper(atlantic,m-1,i)
        ans = []
        for i in range(m):
            for j in range(n):
                if pacific[i][j] and atlantic[i][j]:
                    ans.append((i,j))
        return ans

C++版本如下:

class Solution {
public:
    vector<vector<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>> can_reach_p(M,vector<bool>(N));
        vector<vector<bool>> can_reach_a(M,vector<bool>(N));
        vector<vector<int>> ans;
        
        for (int i=0;i<M;++i){
            dfs(matrix,can_reach_p,i,0);
            dfs(matrix,can_reach_a,i,N-1);
        }
        for (int i=0;i<N;++i){
            dfs(matrix,can_reach_p,0,i);
            dfs(matrix,can_reach_a,M-1,i);
        }
        
        for (int i=0;i<M;++i){
            for (int j=0;j<N;++j){
                if (can_reach_p[i][j] && can_reach_a[i][j]) {
                    ans.push_back({i,j});
                }
            }
        }
        return ans;
    }
    
    void dfs(const vector<vector<int>>& matrix, vector<vector<bool>>& can_reach, int i,int j){
        can_reach[i][j] = true;
        vector<pair<int,int>> dirs = {{0,1},{0,-1},{1,0},{-1,0}};
        for (auto d:dirs){
            int x = i+d.first;
            int y = j+d.second;
            
            if (x<0 || x>=matrix.size() || y<0 || y>=matrix[0].size() || matrix[x][y]<matrix[i][j] || can_reach[x][y]){
                continue;
            }
            dfs(matrix,can_reach,x,y);
        }
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值