首页 > 其他分享 >Leetcode(剑指offer专项训练)——DP专项(8)

Leetcode(剑指offer专项训练)——DP专项(8)

时间:2023-04-09 15:12:48浏览次数:52  
标签:专项 matrix int 单元格 -- DP ans Leetcode dp

最长递增路径

题目

给定一个 m x n 整数矩阵 matrix ,找出其中 最长递增路径 的长度。
对于每个单元格,你可以往上,下,左,右四个方向移动。 不能 在 对角线 方向上移动或移动到 边界外(即不允许环绕)。
链接

DP

但是依旧不能覆盖所有的情况

class Solution {
public:
    int longestIncreasingPath(vector<vector<int>>& matrix) {
        int m=matrix.size();
        int n=matrix[0].size();
        vector<vector<int>>dp(m,vector<int>(n,1));
        int ans=1;
        //右-下
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(i&&matrix[i-1][j]<matrix[i][j]){
                    dp[i][j]=max(dp[i][j],dp[i-1][j]+1);
                }
                if(j&&matrix[i][j-1]<matrix[i][j]){
                    dp[i][j]=max(dp[i][j],dp[i][j-1]+1);
                }
                if(dp[i][j]>=ans){
                    // printf("(%d ,%d),value=%d len=%d\n",i,j,matrix[i][j],dp[i][j]);
                    ans=dp[i][j];
                }
            }
        }
        //左上
        for(int i=m-1;i>=0;i--){
            for(int j=n-1;j>=0;j--){
                if(i+1<m&&matrix[i+1][j]<matrix[i][j]){
                    dp[i][j]=max(dp[i][j],dp[i+1][j]+1);
                }
                if(j+1<n&&matrix[i][j+1]<matrix[i][j]){
                    dp[i][j]=max(dp[i][j],dp[i][j+1]+1);
                }
                if(dp[i][j]>ans){
                    // printf("(%d ,%d),value=%d len=%d\n",i,j,matrix[i][j],dp[i][j]);
                    ans=dp[i][j];
                }
            }
        }
        //右-上
        for(int i=0;i<m;i++){
            for(int j=n-1;j>=0;j--){
                if(i&&matrix[i-1][j]<matrix[i][j]){
                    dp[i][j]=max(dp[i][j],dp[i-1][j]+1);
                }
                if(j+1<n&&matrix[i][j+1]<matrix[i][j]){
                    dp[i][j]=max(dp[i][j],dp[i][j+1]+1);
                }
                if(dp[i][j]>=ans){
                    // printf("(%d ,%d),value=%d len=%d\n",i,j,matrix[i][j],dp[i][j]);
                    ans=dp[i][j];
                }
            }
        }
        //左-下
        for(int i=m-1;i>=0;i--){
            for(int j=0;j<n;j++){
                if(i+1<m&&matrix[i+1][j]<matrix[i][j]){
                    dp[i][j]=max(dp[i][j],dp[i+1][j]+1);
                }
                if(j&&matrix[i][j-1]<matrix[i][j]){
                    dp[i][j]=max(dp[i][j],dp[i][j-1]+1);
                }
                if(dp[i][j]>ans){
                    // printf("(%d ,%d),value=%d len=%d\n",i,j,matrix[i][j],dp[i][j]);
                    ans=dp[i][j];
                }
            }
        }
        /*---第二次--*/
        //右-下
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(i&&matrix[i-1][j]<matrix[i][j]){
                    dp[i][j]=max(dp[i][j],dp[i-1][j]+1);
                }
                if(j&&matrix[i][j-1]<matrix[i][j]){
                    dp[i][j]=max(dp[i][j],dp[i][j-1]+1);
                }
                if(dp[i][j]>=ans){
                    // printf("(%d ,%d),value=%d len=%d\n",i,j,matrix[i][j],dp[i][j]);
                    ans=dp[i][j];
                }
            }
        }
        //左上
        for(int i=m-1;i>=0;i--){
            for(int j=n-1;j>=0;j--){
                if(i+1<m&&matrix[i+1][j]<matrix[i][j]){
                    dp[i][j]=max(dp[i][j],dp[i+1][j]+1);
                }
                if(j+1<n&&matrix[i][j+1]<matrix[i][j]){
                    dp[i][j]=max(dp[i][j],dp[i][j+1]+1);
                }
                if(dp[i][j]>ans){
                    // printf("(%d ,%d),value=%d len=%d\n",i,j,matrix[i][j],dp[i][j]);
                    ans=dp[i][j];
                }
            }
        }
        //右-上
        for(int i=0;i<m;i++){
            for(int j=n-1;j>=0;j--){
                if(i&&matrix[i-1][j]<matrix[i][j]){
                    dp[i][j]=max(dp[i][j],dp[i-1][j]+1);
                }
                if(j+1<n&&matrix[i][j+1]<matrix[i][j]){
                    dp[i][j]=max(dp[i][j],dp[i][j+1]+1);
                }
                if(dp[i][j]>=ans){
                    // printf("(%d ,%d),value=%d len=%d\n",i,j,matrix[i][j],dp[i][j]);
                    ans=dp[i][j];
                }
            }
        }
        //左-下
        for(int i=m-1;i>=0;i--){
            for(int j=0;j<n;j++){
                if(i+1<m&&matrix[i+1][j]<matrix[i][j]){
                    dp[i][j]=max(dp[i][j],dp[i+1][j]+1);
                }
                if(j&&matrix[i][j-1]<matrix[i][j]){
                    dp[i][j]=max(dp[i][j],dp[i][j-1]+1);
                }
                if(dp[i][j]>ans){
                    // printf("(%d ,%d),value=%d len=%d\n",i,j,matrix[i][j],dp[i][j]);
                    ans=dp[i][j];
                }
            }
        }
        return ans;

    }
};

拓扑排序

如果一个单元格的值比它的所有相邻单元格的值都要大,那么这个单元格对应的最长递增路径是1
将矩阵看成一个有向图,计算每个单元格对应的出度,即有多少条边从该单元格出发。
位置(i,j)的出度等于其四个方向的四个单元格中,值大于(i,j)的单元格个数;
接着我们利用BFS进行拓扑排序,从出度为0的单元格开始,找到它们的入节点的位置,也就是比他们小的四周节点位置,更新这些新的节点的出度,将出度为0的再次加入队列
计算出队列的层数,即为最大的递增长度

class Solution {
public:
    //拓扑排序
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    int longestIncreasingPath(vector<vector<int>>& matrix) {
        int m=matrix.size();
        int n=matrix[0].size();
        vector<vector<int>>outdegree(m,vector<int>(n,0));
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                for(int k=0;k<4;k++){
                    int nx=dx[k]+i;
                    int ny=dy[k]+j;
                    if(nx>=0&&nx<m&&ny>=0&&ny<n&&matrix[nx][ny]>matrix[i][j]){
                        outdegree[i][j]++;
                    }
                }
            }
        }
        queue<pair<int,int>>nodes;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(outdegree[i][j]==0){
                    nodes.push({i,j});
                }
            }
        }
        //BFS
        int ans=0;
        while(!nodes.empty()){
            ans++;
            int size=nodes.size();
            for(int i=0;i<size;i++){
                auto [x,y]=nodes.front();
                
                nodes.pop();
                for(int k=0;k<4;k++){
                    int nx=dx[k]+x;
                    int ny=dy[k]+y;
                    if(nx>=0&&nx<m&&ny>=0&&ny<n&&matrix[nx][ny]<matrix[x][y]){
                        outdegree[nx][ny]--;
                        if(outdegree[nx][ny]==0){
                            nodes.push({nx,ny});
                        }
                    }
                }

            }
            
        }
        return ans;
    }
};

标签:专项,matrix,int,单元格,--,DP,ans,Leetcode,dp
From: https://www.cnblogs.com/SaltyCheese/p/17298561.html

相关文章

  • 换根dp
    给定一棵树,树中包含nn个结点(编号11~nn)和n−1n−1条无向边,每条边都有一个权值。请你在树中找到一个点,使得该点到树中其他结点的最远距离最近。输入格式第一行包含整数nn。接下来n−1n−1行,每行包含三个整数ai,bi,ciai,bi,ci,表示点aiai和bibi之间存在一条权值为ci......
  • 「学习笔记」数位 DP
    「学习笔记」数位DP意义不大的题不写了。点击查看目录目录「学习笔记」数位DP概述例题P2657[SCOI2009]windy数思路代码P4317花神的数论题思路P4124[CQOI2016]手机号码思路代码haha数题意思路代码0和1的熟练题意思路代码苍与红的试炼题意思路代码概述数位DP一般......
  • 20230401数位DP
    数位DP数位DP通常指在\([l,r]\)区间中有多少个满足条件\(k\)的个树常见的数据范围都很大也就是说,把数字的枚举,变成数字的构造不要把数字看作是\(10^{18}\)而把数字看作是\(18\)位数的填数过程就是把原本枚举的问题转化为了构造的问题然而数位dp常通过记忆化搜索实现tips:......
  • 2023年4月8日leetcode练习心得
    给你一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。找出只出现一次的那两个元素。你可以按任意顺序返回答案。你必须设计并实现线性时间复杂度的算法且仅使用常量额外空间来解决此问题。 来源:力扣(LeetCode)链接:https://leetcode.cn/problems/sing......
  • leetcode杨辉三角
    给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。在「杨辉三角」中,每个数是它左上方和右上方的数的和。出处:leetcode对于此题可以建立一个vector<vector<int>>,对外层开辟numRows行,对内层开辟从零开始每次加一个,并把头尾都置为一,然后根据杨辉三角的规律填入......
  • Java笔记(14) UDP通讯程序Demo
    实现一个简单的UDP通信程序,仅作为笔记使用网络编程中有三要素:IP、端口号和通信协议,分别用来确定对方在互联网上的地址、指定接受数据的软件和确定数据在网络中传输的规则。IP地址IP地址分为IPv4地址和IPv6地址,这里不做讨论。IPv4地址中分为公网地址(万维网使用)和私有地址(局......
  • Leetcode(剑指offer专项训练)——DFS/BFS专项(1)
    计算除法题目给定一个变量对数组equations和一个实数值数组values作为已知条件,其中equations[i]=[Ai,Bi]和values[i]共同表示等式Ai/Bi=values[i]。每个Ai或Bi是一个表示单个变量的字符串。另有一些以数组queries表示的问题,其中queries[j]=[Cj,Dj]......
  • #yyds干货盘点# LeetCode面试题:爬楼梯
    1.简述:假设你正在爬楼梯。需要n 阶你才能到达楼顶。每次你可以爬1或2个台阶。你有多少种不同的方法可以爬到楼顶呢? 示例1:输入:n=2输出:2解释:有两种方法可以爬到楼顶。1.1阶+1阶2.2阶示例2:输入:n=3输出:3解释:有三种方法可以爬到楼顶。1.1阶+1阶+1阶2.1阶......
  • 数位 dp
    数位\(\text{dp}\)前言谨慎学习此算法。算法讲解AcWing1081.度的数量题意分析:你看到这道题,是不是无从下手?其实题目就是让我们求在\(x\simy\)中,有多少个数分解成\(B\)进制后仅有\(k\)位为\(1\),其余均为\(0\);考虑暴力:从\(x\)枚举到\(y\),将\(i(x\lei\le......
  • [补][leetcode每日一题]1.28
    1664. 生成平衡数组的方案数提示中等107相关企业给你一个整数数组 nums 。你需要选择 恰好 一个下标(下标从 0 开始)并删除对应的元素。请注意剩下元素的下标可能会因为删除操作而发生改变。比方说,如果 nums=[6,1,7,4,1] ,那么:选择删除下标 1 ,剩下的数组为 nums=[6,7,......