24年收尾之作------动态规划<六> 子序列问题(含对应LeetcodeOJ题)

news2025/1/3 17:14:45

目录

引例

 经典LeetCode OJ题

1.第一题

 2.第二题

3.第三题 

 4.第四题

5.第五题

 6.第六题

 7.第七题

引例

OJ传送门 LeetCode<300>最长递增子序列

画图分析:

使用动态规划解决

1.状态表示

dp[i]表示以i位置元素为结尾的子序列中,最长递增子序列的长度

2.状态表示  对于子数组/子序列的问题都可以划分为长度为1,长度大于1两种情况

3.初始化  可以将dp表中的值初始化为最差的情况,即单个值构成子序列,初始化为1

4.填表顺序    从左往右

5.返回值   因为子序列的结束位置是任意的,所以返回值是dp表中的最大值

具体代码:

int lengthOfLIS(vector<int>& nums) 
    {
        int n=nums.size();
        vector<int> dp(n,1);
        int ret=1;
        for(int i=1;i<n;++i)
        {
            for(int j=0;j<i;++j)
             if(nums[j]<nums[i]) dp[i]=max(dp[i],dp[j]+1);
            
            ret=max(ret,dp[i]);
        }
        return ret;
    }

 经典LeetCode OJ题

1.第一题

OJ传送门 LeetCode<376>摆动序列

 画图分析:

使用动态规划解决

1.状态表示

dp[i]表示以i位置元素为结尾的所有子序列中,最长摆动子序列的长度

但在分析时,会发现结尾位置会出现两种情况

因此对于摆动的子序列或子数组,在状态表示时,是需要使用两个状态来表示的 

f[i]表示以i位置元素为结尾的所有子序列中,最后一个位置呈现"上升"趋势的最长摆动序列的长度

f[i]表示以i位置元素为结尾的所有子序列中,最后一个位置呈现"下降"趋势的最长摆动序列的长度

2.状态转移方程----根据子序列构成来分析

3.初始化

可以将f,g表中的值先初始化为最差的情况,即1

4.填表顺序  从左往右两个表一起填

5.返回值  两个表中的最大值

具体代码:

int wiggleMaxLength(vector<int>& nums) 
    {
        int n=nums.size();
        vector<int> f(n,1),g(n,1);
        int ret=1;
        for(int i=1;i<n;++i)//填f[i],g[i]
        {
            for(int j=0;j<i;++j)
            {
                if(nums[j]<nums[i]) f[i]=max(g[j]+1,f[i]);
                else if(nums[j]>nums[i]) g[i]=max(f[j]+1,g[i]);
            }
            ret=max(ret,max(f[i],g[i]));
        }
        return ret;
    }

 2.第二题

OJ传送门 LeetCode<673>最长递增子序列的个数

画图分析:

在使用动态规划解决该题之前,先介绍一个一次遍历求最大值及出现次数的小算法

使用动态规划解决

1.状态表示

dp[i]表示以i位置元素为结尾的所有子序列中,最长递增子序列的个数

但此时如果直接使用此状态表示求解状态转移方程的话,开始就会发现最长的递增子序列的长度是未知的,不能求解其次数,因此得使用两个状态表示来解决

len[i]表示以i位置元素为结尾的所有子序列中,最长递增子序列的长度

count[i]表示以i位置元素为结尾的所有子序列中,最长递增子序列的个数

2.状态转移方程

3.初始化   两个表都初始化为1

4.填表顺序  从左往右

5.返回值   使用小算法找到最长的子序列及出现次数

具体代码:

int findNumberOfLIS(vector<int>& nums) 
    {
        int n=nums.size();
        vector<int> len(n,1),count(n,1);
        int retlen=1,retcount=1;
        for(int i=1;i<n;++i)
        {
            for(int j=0;j<i;++j)
            {
                if(nums[j]<nums[i])
                {
                    //说明是第二次出现,统计以j结尾的最长子序列的个数
                    if(len[j]+1==len[i]) count[i]+=count[j];
                    else if(len[j]+1>len[i]) len[i]=len[j]+1,count[i]=count[j];
                }
            }
            if(retlen==len[i]) retcount+=count[i];
            else if(retlen<len[i]) retlen=len[i],retcount=count[i];
        }
        return retcount;
    }

3.第三题 

OJ传送门 LeetCode<646> 最长数对链

画图分析:

 使用动态规划解决

在使用动态规划解决之前,当以某个位置为结尾来研究问题时,是研究前面位置的状态,填表顺序是从左往右,但示例二在研究[7,8]进行填表时,会发现既可以跟在[1,2]后面,也可以跟在[4,5]后面,在填表时前后都会对其产生影响,因此要做预处理------排序

在做完排序后,就可以正常完成填表

1.状态表示

dp[i]表示以i位置元素为结尾的所有数对链中,最长数对链的长度

2.状态转移方程 

3.初始化

一般将子序列或子数组问题dp表中的值,初始化为最差的情况,此题即1

4.填表顺序   从左往右

5.返回值   返回dp表中的最大值

具体代码:

 int findLongestChain(vector<vector<int>>& pairs) 
    {
        //排序预处理
        sort(pairs.begin(),pairs.end());
        int n=pairs.size();
        vector<int> dp(n,1);
        int ret=1;
        for(int i=1;i<n;++i)
        {
            for(int j=0;j<i;++j)
            {
                if(pairs[j][1]<pairs[i][0]) dp[i]=max(dp[j]+1,dp[i]);
            }
            ret=max(ret,dp[i]);
        }
        return ret;
    }

 4.第四题

OJ传送门 LeetCode<1218> 最长定差子序列

画图分析:

 使用动态规划解决

1.状态表示

dp[i]表示以i位置元素为结尾的所有子序列中,最长的等差子序列的长度

2.状态转移方程

3.初始化

初始化第一个位置的值 hash[arr[0]]=1

4.填表顺序   从左往右

5.返回值   dp表中的最大值

具体代码:

int longestSubsequence(vector<int>& arr, int difference) 
    {
        unordered_map<int,int> hash;//<arr[i],dp[i]>
        hash[arr[0]]=1;//初始化
        int ret=1;
        for(int i=1;i<arr.size();++i)
        {
            hash[arr[i]]=hash[arr[i]-difference]+1;
            ret=max(ret,hash[arr[i]]);
        }
        return ret;
    }

5.第五题

OJ传送门 LeetCode<1218> 最长的斐波那契子序列的长度

画图分析:

 使用动态规划解决

1.状态表示

dp[i]表示以i位置元素为结尾的所有子序列中,最长的斐波那契子序列的长度

如果使用此状态表示来研究状态转移方程的话,会发现i前面的j位置的dp[j]对应的arr[j]是可能跟在某个值后面的,就不能贸然使用dp[j]来更新dp[i],可以使用二维来确定

dp[i][j]表示以i位置及j位置元素为结尾的所有子序列中,最长的斐波那契额子序列的长度(i<j)

2.状态转移方程

3.初始化  表中所有值都初始化为2

此时可能会想,对于dp[0][0]初始化为2的话,根据状态表示是不正确的,但i<j,这就说明在填表时,只会用到上三角区域的值,因此这些值初始化为多少都不重要,是使用不到的

 

4.填表顺序   从上往下

5.返回值   dp表中的最大值   但此时得判断若数组是[1,2,4]是没有斐波那契子序列的,此时返回值ret的结果为2,根据题意是要为0的,因此需要做 ret<3? 0:ret;

具体代码:

int lenLongestFibSubseq(vector<int>& arr) 
    {
        int n=arr.size();
        //预处理使值与下标绑定
        unordered_map<int,int> hash;//<value,index>
        for(int i=0;i<n;++i) hash[arr[i]]=i;
        vector<vector<int>> dp(n,vector<int>(n,2));
        int ret=2;
        for(int j=2;j<n;++j)//固定最后一个位置
        {
            for(int i=1;i<j;++i)//固定倒数第二个位置
            {
                int a=arr[j]-arr[i];
                if(a<arr[i] && hash.count(a)) dp[i][j]=dp[hash[a]][i]+1;
                ret=max(ret,dp[i][j]);
            }
        }
        return ret<3? 0:ret;
    }

 6.第六题

OJ传送门 LeetCode<1218> 最长等差数列

画图分析:

 使用动态规划解决

1.状态表示

dp[i]表示以i位置元素为结尾的所有子序列中,最长的等差子序列的长度

但在研究状态转移方程时,使用i位置前面的状态(dp[j])填dp[i]时,就会发现,我们只知道dp[j]是一个长度值,并不知道其具体的子序列的情况,可能在其后面跟nums[i]的话,构不成等差子序列,因此可以使用二维的来处理

dp[i][j]表示以i位置及j位置元素为结尾的所有子序列中,最长的等差序列的长度

2.状态转移方程

3.初始化

4.填表顺序

5.返回值    整个dp表中的最大值

具体代码:

int longestArithSeqLength(vector<int>& nums) 
    {
        //优化
        unordered_map<int,int> hash;
        hash[nums[0]]=0;

        int n=nums.size();
        vector<vector<int>> dp(n,vector<int>(n,2));//创建dp表+初始化

        int ret=2;
        for(int i=1;i<n;++i)//固定倒数第二个数
        {
            for(int j=i+1;j<n;++j)//枚举倒数第一个位置
            {
                int a=2*nums[i]-nums[j];
                if(hash.count(a) && hash[a]<i) dp[i][j]=dp[hash[a]][i]+1;
                ret=max(ret,dp[i][j]);
            }
            hash[nums[i]]=i;
        }
        return ret;
    }

 7.第七题

OJ传送门 LeetCode<1218> 等差数列划分 II - 子序列

画图分析:

 使用动态规划解决

1.状态表示

dp[i]表示以i位置元素为结尾的所有子序列中,等差子序列的个数

dp[i][j]表示以i位置及j位置元素为结尾的所有子序列中,等差子序列的个数(i<j)

2.状态转移方程

3.初始化

可以先全部初始化为最差的情况,即i,j单独构成一个子序列,但这不是一个等差序列,结果为0,因此可以先全部初始化为0

4.填表顺序

先固定倒数第一个数,再枚举倒数第二个数

5.返回值   整个dp表的和

具体代码:

int numberOfArithmeticSlices(vector<int>& nums) 
    {
        //优化
        int n=nums.size();
        unordered_map<long long,vector<int>> hash;
        for(int i=0;i<n;++i) hash[nums[i]].push_back(i);
       
        int sum=0;
        vector<vector<int>> dp(n,vector<int>(n));
        for(int j=2;j<n;++j)//固定倒数第一个数,要使其有意义的话,从2开始
        {
            for(int i=1;i<j;++i)//固定倒数第二个数
            {
                long long a=(long long)2*nums[i]-nums[j];
                if(hash.count(a))
                {
                    for(auto k:hash[a])
                    {
                        if(k<i) dp[i][j]+=dp[k][i]+1;
                    }
                }
                sum+=dp[i][j];
            }
        }
        return sum;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2269094.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

蓝牙|软件 Qualcomm S7 Sound Platform开发系列之初级入门指南

本文适用范围 ADK24.2~ 问题/功能描述 S7开发环境搭建与编译介绍 实现方案 本文介绍适用于windows平台Application部分,audio ss的说明会在下一篇文章在做说明,Linux平台如果不进行AI算法的开发,个人认知是没有必要配置,若是做服务器倒是不错的选择.因为编译完成后烧录调试还…

Redis - 4 ( 9000 字 Redis 入门级教程 )

一&#xff1a; Zset 有序集合 1.1 常用命令 有序集合在 Redis 数据结构中相较于字符串、列表、哈希和集合稍显陌生。它继承了集合中元素不允许重复的特点&#xff0c;但与集合不同的是&#xff0c;有序集合的每个元素都关联一个唯一的浮点分数&#xff08;score&#xff09;…

ubuntu 使用samba与windows共享文件[注意权限配置]

在Ubuntu上使用Samba服务与Windows系统共享文件&#xff0c;需要正确配置Samba服务以及相应的权限。以下是详细的步骤&#xff1a; 安装Samba 首先&#xff0c;确保你的Ubuntu系统上安装了Samba服务。 sudo apt update sudo apt install samba配置Samba 安装完成后&#xff0c…

打印进度条

文章目录 1.Python语言实现(1)黑白色(2)彩色&#xff1a;蓝色 2.C语言实现(1)黑白颜色(2)彩色版&#xff1a;红绿色 1.Python语言实现 (1)黑白色 import sys import timedef progress_bar(percentage, width50):"""打印进度条:param percentage: 当前进度百分比…

深度解析 LDA 与聚类结合的文本主题分析实战

🌟作者简介:热爱数据分析,学习Python、Stata、SPSS等统计语言的小高同学~🍊个人主页:小高要坚强的博客🍓当前专栏:《Python之文本分析》🍎本文内容:深度解析 LDA 与聚类结合的文本主题分析实战🌸作者“三要”格言:要坚强、要努力、要学习 目录 引言 技术框架…

点跟踪基准最早的论文学习解读:TAP-Vid: A Benchmark for Tracking Any Point in a Video—前置基础

TAP-Vid: A Benchmark for Tracking Any Point in a Video— TAP-Vid&#xff1a;跟踪视频中任意点的基准、 学习这一篇文章的本来的目的是为了学习一下TAP-NET便于理解后面用到的TAPIR方法的使用。 文章目录 TAP-Vid: A Benchmark for Tracking Any Point in a Video— TAP-V…

C进阶-字符串与内存函数介绍(另加2道典型面试题)

满意的话&#xff0c;记得一键三连哦&#xff01; 我们先看2道面试题 第一道&#xff1a; 我们画图理解&#xff1a; pa&#xff0c;先使用再&#xff0c;pa开始指向a【0】&#xff0c;之后pa向下移动一位&#xff0c;再解引用&#xff0c;指向a【1】&#xff0c;a【1】又指向…

PH47代码框架 24241231 重要更新

仪式感一下&#xff1a;2024年最后一天&#xff0c;发布 PH47 代码框架的一次重要更新。当然这并不是有意的&#xff0c;而是直到现在才把更新的所有工作全部做完&#xff08;希望确实如此&#xff09;。 本次更新要点&#xff1a; 1、加入多IMU支持。本次更新正式加入对 MPU65…

idea报错:There is not enough memory to perform the requested operation.

文章目录 一、问题描述二、先解决三、后原因&#xff08;了解&#xff09; 一、问题描述 就是在使用 IDEA 写代码时&#xff0c;IDEA 可能会弹一个窗&#xff0c;大概提示你目前使用的 IDEA 内存不足&#xff0c;其实就是提醒你 JVM 的内存不够了&#xff0c;需要重新分配。弹…

Python用K-Means均值聚类、LRFMC模型对航空公司客户数据价值可视化分析指标应用|数据分享...

全文链接&#xff1a;https://tecdat.cn/?p38708 分析师&#xff1a;Yuling Fang 信息时代的来临使得企业营销焦点从产品中心转向客户中心&#xff0c;客户关系管理成为企业的核心问题&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。 客户关系管理的关键是客…

Linux umami网站统计工具自定义API开发

Linux umami网站统计工具自定义API开发 一、src/queries/analytics/下添加调用sql查询文件&#xff1a;二、src/queries/index.js文件中增加导出模块内容&#xff1a;三、src/pages/api/下根据目录添加接口方法文件&#xff1a;四、构建项目&#xff0c;启动。1、到umami目录&a…

基于SpringBoot的实验室信息管理系统【源码+文档+部署讲解】

系统介绍 视频演示 基于SpringBootVue实现的实验室信息管理系统采用前后端分离的架构方式&#xff0c;系统分为管理员、老师、用户三种角色&#xff0c;实现了用户管理、设备管理、实验室查询、公告、课程、实验室耗材管理、我的等功能 技术选型 开发工具&#xff1a;idea2…

【openGauss】正则表达式次数符号“{}“在ORACLE和openGauss中的差异

一、前言 正则作为一种常用的字符串处理方式&#xff0c;在各种开发语言&#xff0c;甚至数据库中&#xff0c;都有自带的正则函数。但是正则函数有很多标准&#xff0c;不同标准对正则表达式的解析方式不一样&#xff0c;本次在迁移一个ORACLE数据库到openGauss时发现了一个关…

SSM-Spring-IOC/DI对应的配置开发

目录 一、IOC 控制反转 1.什么是控制反转呢 2. Spring和IOC之间的关系是什么呢? 3.IOC容器的作用以及内部存放的是什么? 4.当IOC容器中创建好service和dao对象后&#xff0c;程序能正确执行么? 5.Spring 容器管理什么内容&#xff1f; 6.如何将需要管理的对象交给 …

docker中使用nginx

宿主机和docker中nginx做映射 宿主机中nginx 映射目录 /root/myDockerData/devnginx 在容器中相关位置分别是&#xff1a; 配置文件位置&#xff1a;/etc/nginx/ 日志位置&#xff1a;/var/log/nginx/ 项目位置&#xff1a;/usr/share/nginx/html 如下配置启动命令行&#x…

Rocky Linux下安装meld

背景介绍&#xff1a; meld是一款Linux系统下的用于 文件夹和文件的比对软件&#xff0c;非常常用&#xff1b; 故障现象&#xff1a; 输入安装命令后&#xff0c;sudo yum install meld&#xff0c;报错。 12-31 22:12:17 ~]$ sudo yum install meld Last metadata expirat…

Python中PDF转Word的技术

Python PDF转Word技术概述 在日常办公和数据处理中&#xff0c;经常需要将PDF文档转换为Word文档&#xff0c;以便进行编辑、修改或格式调整。Python作为一种强大的编程语言&#xff0c;提供了多种库和工具来实现这一功能。以下是对Python中PDF转Word技术的详细介绍。 一、技…

混合并行训练框架性能对比

混合并行训练框架性能对比 1. 框架类型 DeepSpeed、Megatron - LM、Colossal - AI、SageMaker、Merak、FasterMoE、Tutel、Whale、Alpa、DAPPLE、Mesh - TensorFlow 2. 可用并行性(Available parallelisms) DNN framework(深度神经网络框架)DP(数据并行,Data Parallelis…

python24-常用的第三方库02:openpyxl模块、pdfplumber模块

一、openpyxl模块 openpyxl 是一个用于读取和写入 Excel 2010 xlsx/xlsm/xltx/xltm 文件的 Python 库。 它允许你以编程方式操作 Excel 文件&#xff0c;包括创建新的工作簿、修改现有的工作簿、添加或删除工作表、读写单元格数据等。 1-1、安装openpyxl模块 验证&#xff1a…

npm ERR! ECONNRESET 解决方法

问题&#xff1a;npm 命令遇到的错误是 ECONNRESET&#xff0c;这通常与网络连接问题相关。设置代理解决问题。 一、查看当前代理设置 npm config get proxy npm config get https-proxy二、设置代理 npm config set proxy http://your-proxy-address:port npm config set h…