LeetCode 329. Longest Increasing Path in a Matrix

知识点

拓扑排序 或者 动态规划

结果

拓扑排序

在这里插入图片描述

动态规划

在这里插入图片描述

代码

拓扑排序

//就是返回拓扑排序的层数吧
//拓扑信息是大于关系吧
class Solution {
public:
    int longestIncreasingPath(vector<vector<int>>& matrix) {
        //得到矩阵的长宽,总大小
        int h = matrix.size();
        if(h == 0){
            return 0;
        }

        int w = matrix[0].size();
        int max = h * w;

        //邻接表,表示before < after,并且after在before的四个方向,数组下标从0开始
        vector<vector<int>> adj(max+10);
        //入度数组
        vector<int> inDegree(max+10,0);

        //将矩阵数组展开进行存储
        vector<int> arr;
        for(int i=0;i<h;i++){
            for(int j=0;j<w;j++){
                arr.push_back(matrix[i][j]);
            }
        }

        //上下左右
        int up;
        int down;
        int left;
        int right;

        for(int i=0;i<max;i++){
            up = i-w;
            down = i+w;
            left = i-1;
            right = i+1;
            if(up>=0 && arr[up] > arr[i]){
                adj[i].push_back(up);
                inDegree[up]++;
            }
            if(down<max && arr[down] > arr[i]){
                adj[i].push_back(down);
                inDegree[down]++;
            }
            if(i%w !=0 && arr[left] > arr[i] ){
                adj[i].push_back(left);
                inDegree[left]++;
            }
            if(right%w != 0 && arr[right] > arr[i]){
                adj[i].push_back(right);
                inDegree[right]++;
            }
        }
 
        //下面进行拓扑排序
        int length = topoSort(adj,inDegree,max);
        return length;
    }

    int topoSort(vector<vector<int>>& adj,vector<int>& inDegree,int max){
        queue<int> q;
        
        for(int i=0;i<inDegree.size();i++){
            if(inDegree[i] == 0){
                q.push(i);
            }
        }

        int length = 0;
        while(!q.empty()){
            length++;

            int s = q.size();

            for(int i=0;i<s;i++){
                int before = q.front();
                q.pop();

                for(int i=0;i<adj[before].size();i++){
                    int after = adj[before][i];
                    inDegree[after]--;

                    if(inDegree[after] == 0){
                        q.push(after);
                    }
                }

            }

        }
        return length;
    }
};

动态规划

//使用DFS+DP来解题
//DP的作用是记忆化搜索的作用
//这里面没有指定数组的大小,所以我们的dp数组使用vector
#include <bits/stdc++.h>
using namespace std;
class Solution {

private:
    //长度
    int h;
    //宽度
    int w;
    //动态dp数组
    vector<vector<int>> dp;
    //相对方位数组,储存四个方向,上下左右
    int dr[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};

public:
    int longestIncreasingPath(vector<vector<int>>& matrix) {
        //长度
        h = matrix.size();
        //特判matrix为空
        if(h == 0){
            return 0;
        }
        //宽度
        w = matrix[0].size();

        //为dp数组赋值大小和值,所有的值最原始都是0
        dp.assign(h,vector<int>(w,0));

        //最大长度
        int maxLen = 0;

        for(int i=0;i<h;i++){
            for(int j=0;j<w;j++){
                maxLen = max(maxLen,DFS(matrix,i,j));
            }
        }

        return maxLen;
    }

    int DFS(vector<vector<int>>& matrix,int x,int y){
        //记忆化搜索价值所在:不为零,说明一定是已经进行了DFS的,那它的值绝对确定了
        if(dp[x][y] != 0){
            return dp[x][y];
        }
        //否则进行计算
        //前后左右四个方位的dp,取max那种
        //dp初始化1
        dp[x][y] = 1;
        for(int k=0;k<4;k++){
            //n表示neighbor!
            int nx = x+dr[k][0];
            int ny = y+dr[k][1];
            //不超出边界,而且邻居还小于自己,进行DFS继续搜索
            if(nx>=0 && nx < h && ny >=0 && ny < w && matrix[nx][ny] <matrix[x][y]){
                //进行记忆化存储!!!
                dp[x][y] = max(dp[x][y],1+DFS(matrix,nx,ny));
            }
        }
        return dp[x][y];
    }
};

反思

拓扑排序

  1. 要不是看见这道题目出现在拓扑排序里面,我可能根本想不到要用拓扑排序😓,我之前一直以为拓扑排序都是判断DAG,这次长见识了,我应该会首选动态规划的;
  2. LeetCode居然不能debug,肉眼debug太难了!!!
  3. 注意拓扑排序循环体与平常的写法不一样,这里是一次性把同一层的都遍历一个遍,这样是为了方便记录层数layer,我之前没想到,结果用了一个结构体存储层数,太笨了;
  4. 要理解拓扑排序的那张分层的结构图,感觉那个就是拓扑排序的思想,要用拓扑排序,就看可不可以套用那张分层结构图,套得上就可以用拓扑排序
  5. 特判matrx为空的情况,难顶。

动态规划

  1. 对于DFS+动态规划(即记忆化搜索,真的好常见的考法),DFS的递归边界一般就是dp[i][j]已经得到,直接return dp[i][j]DFS(i,j)的含义更像是返回dp[i][j],如果没有则给dfs计算dp[i][j],反正我要返回dp[i][j],在这其中用到了动态规划的思想,将大问题分解成规模小一点的问题
  2. 学会了vector.assign(),开心~~~
  3. 对于前后左右,我们一般还是用相对位置加减,这样代码更加清晰!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值