LeetCode 417. 太平洋大西洋水流问题

在这里插入图片描述设置两个数组,记录当前节点是否能够能流向太平洋和大西洋,从边界开始扩展, 能够扩展到的结点表示该节点能够流向太平洋或者大西洋,最后两个数组标志都1的坐标结点即为正确答案。

class Solution {
public:    
    int tp[155][155];
    int dx[155][155];
    int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
    vector<vector<int> >ans;
    void dfs(vector<vector<int>>& matrix,int vis[][155],int x,int y){
        vis[x][y]=1;
        for(int i=0;i<4;i++){
            int xx=x+dir[i][0];
            int yy=y+dir[i][1];
            if(xx<0||xx>=matrix.size()||yy<0||yy>=matrix[0].size()||vis[xx][yy])
                continue;
            if(matrix[x][y]<=matrix[xx][yy])
                dfs(matrix,vis,xx,yy);
        }
        
    }
    
    vector<vector<int>> pacificAtlantic(vector<vector<int>>& matrix) {
        int r=matrix.size();
        if(r==0)
            return {};
        int c=matrix[0].size();
        for(int i=0;i<r;i++){
            dfs(matrix,dx,i,c-1);
            dfs(matrix,tp,i,0);
        }
        
        for(int j=0;j<c;j++){
            dfs(matrix,tp,0,j);
            dfs(matrix,dx,r-1,j);
        }
        for(int i=0;i<r;i++)
            for(int j=0;j<c;j++)
                if(tp[i][j]&&dx[i][j])
                    ans.push_back({i,j});
        return ans;
        
        
    }
};

我原来是这么做的,从任一结点出发,如果这个节点能够扩展到边界,说明这个节点到边界上的路径都可以到达这个边界,所以可以采用记忆化搜索。
但是这样有一个问题,在每次从一个结点开始扩展时,都必须初始化vis数组,因为有这样一种情况:若不初始化vis数组,A能够流向B再流向边界,但是C跟A的高度等高,A流向C后发现从C不能流向边界,但在下一次搜索时,C的vis已经访问过了,所以会直接返回C不能流向边界的结果,但其实C是能够流向A再流向边界的。这样做的效率不如上面这种高。
下图是两种方法的时间对比:
在这里插入图片描述
代码:

class Solution {
public:
    int tp[155][155];
    int dx[155][155];
    int f[155][155];
    int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
    int row,col;
    int vis[155][155];
    vector<vector<int> > ans;
    
    pair<bool,bool> dfs(int r,int c,vector<vector<int>>& m){
        if(vis[r][c]){
            return pair<bool,bool>(tp[r][c],dx[r][c]);
        }
        vis[r][c]=1;
        if(r==0||c==0)
            tp[r][c]=1;
        if(r==row-1||c==col-1)
            dx[r][c]=1;
                
        for(int i=0;i<4;i++){
            int rr=r+dir[i][0];
            int cc=c+dir[i][1];
            if(rr<0||rr>row-1||cc<0||cc>col-1||m[rr][cc]>m[r][c])
                continue;
            pair<bool,bool> p;
            if(vis[rr][cc])
                p= make_pair(tp[rr][cc],dx[rr][cc]);
            else
                p=dfs(rr,cc,m);
            
            tp[r][c]=tp[r][c]||p.first;
            dx[r][c]=dx[r][c]||p.second;
        }
        f[r][c]=tp[r][c]&&dx[r][c];
        return pair<bool,bool>(tp[r][c],dx[r][c]);
    }
    
    vector<vector<int> > pacificAtlantic(vector<vector<int>>& matrix) {
        if(matrix.size()==0)
            return {};
        row=matrix.size();
        col=matrix[0].size();
        
        memset(f,-1,sizeof f);
                
        for(int i=0;i<row;i++)
            for(int j=0;j<col;j++){
                if(tp[i][j]&&dx[i][j]){
                    ans.push_back({i,j});
                    continue;
                }
                memset(vis,0,sizeof vis);
                pair<bool,bool>p=dfs(i,j,matrix);
                if(p.first&&p.second){
                    ans.push_back({i,j});
                }
            }
        return ans;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值