牛客网:矩阵最长递增路径

23 篇文章 2 订阅
2 篇文章 0 订阅

 

很典型的搜索题目,一共有两种方法可以做。即深搜和广搜。

目录

1.深搜

2.广搜


1.深搜

这里的深搜有点动态规划的味道。

我们设置一个dp数组代表以当前节点为起点能够走的最长路径。这有个好处就是之后我们遍历到这个点的时候不必再去搜索一遍了。

首先要想明白一件事,那就是,如果有一条最长路径,那么这条路径上的所有点的最长路径都是这一条。否则原来的最长二字不成立。基于此,我们一次搜索就可以求出该路径上所有点的最长路径值。

于是对于每一个遍历到的坐标,我们进行如下操作:

如果dp[x][y]不为0,说明之前已经生成了其最长路径,则直接返回。

否则说明dp[x][y]为0,说明还未求出以该节点为起点的最长路径。此时我们初始化dp为,假定最长路径只包含当前这个节点。

之后:

对四个方位的节点进行处理,当某个方位的点合法并且这个点的数值大于当前节点的数值,我们可以继续递归,然后取dp[i][j]=max(dp[i][j],dfs+1),这里的dfs即是我们的递归函数

返回dp[x][y]

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 递增路径的最大长度
     * @param matrix int整型vector<vector<>> 描述矩阵的每个数
     * @return int整型
     */
    const int dir_X[4]={0,0,-1,1};
    const int dir_Y[4]={-1,1,0,0};
    bool isValid(vector<vector<int>> &matrix,int x,int y){
        return x>=0&&x<matrix.size()&&y>=0&&y<matrix[0].size();
    }
    
    int dfs(vector<vector<int> >& matrix, vector<vector<int>> &dp,int x,int y){
        if(dp[x][y]!=0){
            return dp[x][y];
        }
        dp[x][y]++;
        for(int i=0;i<4;++i){
            int dx=x+dir_X[i];
            int dy=y+dir_Y[i];
            if(isValid(matrix, dx, dy) && matrix[x][y]<matrix[dx][dy]){
                dp[x][y]=max(dp[x][y],dfs(matrix,dp,dx,dy)+1);
            }
        }
        return dp[x][y];
    }

    int solve(vector<vector<int> >& matrix) {
        int res=0;
        vector<vector<int>> dp(matrix.size(),vector<int>(matrix[0].size(),0));
        for(int i=0;i<matrix.size();++i){
            for(int j=0;j<matrix[0].size();++j){
                res=max(res,dfs(matrix,dp,i,j));
            }
        }
        return res;
    }
};

2.广搜

除了深搜外,我们还能用广搜来实现反向寻找路径。

我们用一点数据结构的知识,记录每个节点的出度,然后出度为0的点就是我们开始广搜的节点。

思路如下所示:

首先求出所有点的出度,然后将出度为0的点先压入队列中。

接下来进行BFS,当队列不空时进行如下操作:

1.求出当前层的size

2.对size内的队列前部坐标进行如下操作:

求得合法的,并且坐标值是小于当前节点的坐标(这里是反过来的,因为我们是从终点向起点搜索),然后将对应的方位的坐标节点的出度减1,当此该节点的出度为0时,说明从该节点能到达路径都已遍历过,于是将该节点压入队列。

最长的路径一定会让队列不为空的状态持续到最后,代码如下所示:

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 递增路径的最大长度
     * @param matrix int整型vector<vector<>> 描述矩阵的每个数
     * @return int整型
     */
    const int dir_X[4]={0,0,-1,1};
    const int dir_Y[4]={-1,1,0,0};
    bool isValid(vector<vector<int>> &matrix,int x,int y){
        return x>=0&&x<matrix.size()&&y>=0&&y<matrix[0].size();
    }
    int solve(vector<vector<int> >& matrix) {
        int row=matrix.size(),col=matrix[0].size();
        vector<vector<int>> outdegree(row,vector<int>(col));
        for(int i=0;i<row;++i){
            for(int j=0;j<col;++j){
                for(int k=0;k<4;++k){
                    int dx=i+dir_X[k];
                    int dy=j+dir_Y[k];
                    if(isValid(matrix, dx, dy) && matrix[i][j]<matrix[dx][dy]){
                        outdegree[i][j]++;
                    }
                }
            }
        }
        queue<pair<int, int>>q;
        for(int i=0;i<row;++i){
            for(int j=0;j<col;++j){
                if(!outdegree[i][j]){
                    q.push({i,j});
                }
            }
        }
        int res=0;
        while(!q.empty()){
            res++;
            int size=q.size();
            for(int x=0;x<size;++x){
                pair<int, int> tmp=q.front();
                q.pop();
                int i=tmp.first;
                int j=tmp.second;
                for(int k=0;k<4;++k){
                    int dx=i+dir_X[k];
                    int dy=j+dir_Y[k];
                    if(isValid(matrix, dx, dy) && matrix[i][j]>matrix[dx][dy]){
                        outdegree[dx][dy]--;
                        if(outdegree[dx][dy]==0){
                            q.push({dx,dy});
                        }
                    }
                }
            }
            
        }
        return res;
    }
};

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值