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

目录

引例

 经典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.mzph.cn/pingmian/65701.shtml

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

相关文章

使用 ASP.NET Core wwwroot 上传和存储文件

在 ASP.NET Core 应用程序中上传和存储文件是用户个人资料、产品目录等功能的常见要求。本指南将解释使用wwwroot存储图像&#xff08;可用于文件&#xff09;的过程以及如何在应用程序中处理图像上传。 步骤 1&#xff1a;设置项目环境 确保您的 ASP.NET 项目中具有必要的依…

格式化输出年月日

直接上图 结论&#xff1a;老老实实用yyyy&#xff0c;得到的年月日是我们口头上说的时间&#xff0c;而YYYY有点反人类.... 对于一年的最后一周的一些日子&#xff0c;会统计成下一年&#xff1b; 对于下一年的第一周的一些日子&#xff0c;会统计成上一年&#xff1b; 你猜…

一文详解串行、并行、同步、异步

串行、并行、同步和异步是计算机科学和电子学中常见的概念&#xff0c;涉及数据传输、处理和通信的方式。它们各自有不同的应用场景和特点。以下是这四个概念的详细解释&#xff1a; 1. 串行&#xff08;Serial&#xff09; 定义&#xff1a; 串行指的是数据在传输过程中按位…

html5css3

1.html5新增语义化标签 <header><nav><article><section><aside><footer> 2.新增多媒体标签 视频<video>格式&#xff1a;map4,webm,ogg <video controls"controls" autoplay"autoplay" muted"mute…

【超级详细】七牛云配置阿里云域名详细过程记录

0. 准备一个阿里云域名&#xff0c;记得要备案&#xff01;&#xff01;&#xff01;&#xff01; 1. 创建七牛云存储空间 首先&#xff0c;登录七牛云控制台&#xff0c;创建一个新的存储空间&#xff08;Bucket&#xff09;。这个存储空间将用于存放你的文件&#xff0c;并…

Cornerstone3D:了解Nifti文件,并查看元数据

Nifti 全称Neuroimaging Informatics Technology Initiative是一种专为存储医学和神经影像数据而设计的文件格式。设计目的是高效的存储三维或四维图像数据&#xff0c;同时将相关的元数据紧凑地嵌入文件中。Nifti文件的组成&#xff1a;头信息&#xff08;元数据&#xff09;…

【C++】2029:【例4.15】水仙花数

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目描述&#x1f4af;我的做法思路分析优势不足之处 &#x1f4af;老师的做法思路分析优势不足 &#x1f4af;对比和优化实现方式对比优化思路和操作1. 直接分解数字的各位…

形象地理解UE4中的数据结构 TLinkedListBase

大家都熟知链表&#xff0c;但不一定能快速看懂UE4中的数据结构。 TLinkedListBase表示“链接”中的一个结点&#xff0c;有三个成员&#xff1a; 一、ElementType Element; 表示具体的业务&#xff0c;例如int链条中的一个整数。 二、NextLink 表示 “下一个Node”&#…

RabbitMQ基础篇之Java客户端 Work Queues

文章目录 模型概述需求实现步骤创建队列定义消费者定义消息发送测试执行观察结论多消费者的作用性能差异生产环境中的应用 处理速度差异的情况 优化示例总结 模型概述 Work Queues 模型也称为任务模型&#xff0c;多个消费者绑定到同一个队列&#xff0c;共同消费队列中的消息…

CP AUTOSAR标准之FlexRayDriver(AUTOSAR_SWS_FlexRayDriver)(更新中……)

1 简介和功能概述 FlexRay驱动程序(Fr)抽象了特定FlexRay通信控制器(CC)的硬件相关实现细节。本规范主要依赖于符合FlexRay规范[13]的FlexRay CC。此外,本规范还支持符合FlexRay规范[14]的旧版FlexRay控制器。本SWS中因支持的FlexRay规范不同而导致的不同行为在适用的情况下以…

vscode代码AI插件Continue 安装与使用

“Continue” 是一款强大的插件&#xff0c;它主要用于在开发过程中提供智能的代码延续功能。例如&#xff0c;当你在编写代码并且需要进行下一步操作或者完成一个代码块时&#xff0c;它能够根据代码的上下文、语法规则以及相关的库和框架知识&#xff0c;为你提供可能的代码续…

ubuntu 如何使用vrf

在Ubuntu或其他Linux系统中&#xff0c;您使用ip命令和sysctl命令配置的网络和内核参数通常是临时的&#xff0c;这意味着在系统重启后这些配置会丢失。为了将这些配置持久化&#xff0c;您需要采取一些额外的步骤。 对于ip命令配置的网络接口和路由&#xff0c;您可以将这些配…

二、SQL语言,《数据库系统概念》,原书第7版

文章目录 一、概览SQL语言1.1 SQL 语言概述1.1.1 SQL语言的提出和发展1.1.2 SQL 语言的功能概述 1.2 利用SQL语言建立数据库1.2.1 示例1.2.2 SQL-DDL1.2.2.1 CREATE DATABASE1.2.2.2 CREATE TABLE 1.2.3 SQL-DML1.2.3.1 INSERT INTO 1.3 用SQL 语言进行简单查询1.3.1 单表查询 …

【ArcGIS Pro/GeoScene Pro】可视化时态数据

可视化过去二十年新西兰国际旅游业的发展变化 工程数据下载 ArcGIS Pro 快速入门指南—ArcGIS Pro | 文档 添加数据 数据为中国旅客数据 转置表字段 列数据转行数据

WebRTC :原理、协议和应用场景

WebRTC&#xff08;Web Real-Time Communication&#xff09;是一种用于在Web浏览器和移动应用程序之间进行实时通信的开放标准。它通过将音频、视频和数据传输集成到Web浏览器中&#xff0c;使得实时通信变得简单且无需任何插件或第三方软件。 一、WebRTC 的原理 WebRTC的实…

git在idea中操作频繁出现让输入token或用户密码,可以使用凭证助手(使用git命令时输入的用户密码即可) use credential helper

1、打开 idea 设置&#xff0c;找到 git 路径 File | Settings | Version Control | Git 2、勾选 Use credential helper 即可

CPT203 Software Engineering 软件工程 Pt.5 软件测试(中英双语)

文章目录 8. 软件测试8.1 Testing&#xff08;测试&#xff09;8.1.1 A note of testing under the V & A framework8.1.2 The Basics8.1.3 The Goals8.1.4 The Stages 8.2 Developing testing&#xff08;开发测试&#xff09;8.2.1 Unit testing&#xff08;单元测试&…

Docker基础知识 Docker命令、镜像、容器、数据卷、自定义镜像、使用Docker部署Java应用、部署前端代码、DockerCompose一键部署

目录 1.Docker 2.镜像和容器 2.1 定义 2.2 开机自动启动容器 3.docker命令 3.1 docker run 参数说明 3.2 常见命令 3.3 命令演示 3.4 命令别名 4.Docker命令详解 5.数据卷 5.1 定义 5.2 数据卷的相关命令 5.3 数据卷命令 5.4 挂载本地目录或文件 5.4.1 定义 5.4.2 mysql容器目录…

探索CSDN博客数据:使用Python爬虫技术

探索CSDN博客数据&#xff1a;使用Python爬虫技术 在数字化的浪潮中&#xff0c;数据的获取与分析变得日益关键。CSDN作为中国领先的IT社区和服务平台&#xff0c;汇聚了海量的技术博客与文章&#xff0c;成为一座蕴藏丰富的数据宝库。本文将引领您穿梭于Python的requests和py…

Python 自动化 打开网站 填表登陆 例子

图样 简价&#xff1a; 简要说明这个程序的功能&#xff1a; 1. **基本功能**&#xff1a; - 自动打开网站 - 自动填写登录信息&#xff08;号、公司名称、密码&#xff09; - 显示半透明状态窗口实时提示操作进度 2. **操作流程**&#xff1a; - 打开网站后自动…