当前位置: 首页 > news >正文

最长上升/下降子序列的长度(动态规划)

一.最长上升子序列

1.什么是最长上升子序列:

定义:子序列是从数组中删除部分元素(不改变顺序)得到的序列。不下降指序列中每个元素>=前一个元素。LIS即长度最长的不下降子序列。
示例:数组nums=[3,1,2,4,3]的LIS为[1,2,4]或[1,2,3],
长度=3。
应用价值:任务调度、股票买卖等。

2.动态规划原理:

核心思想:用动态规划记录以每个元素结尾的LIS长度。
状态定义:dp[i]表示以a[i]结尾的最长不下降子序列长度。
转移方程:dp[i] = max(dp[j]+1),其中j<i且a[j]≤a[i]。
初始条件:所有dp[i]=1(单个元素自成子序列)。
最终结果:max(dp[0...n-1])即为LIS长度。

3.数据示例:

        原数组a记录具体数据

31243
01234

                i=0:        nums[0]=3→无前驱元素,dp[0]=1
i=1:        nums[1]=1→j=0(3>1不满足)→dp[1]=1
i=2:        nums[2]=2→j=1(1<2→dp[1]+1=2)→dp[2]=2
i=3:        nums[3]=4→j=0,1,2(取j=2,dp[2]+1=3)→dp[3]=3
i=4:        nums[4]=3→j=0,1,2(取j=2,dp[2]+1=3)→dp[4]=3

        dp[i]记录到i位置,最长不下降子序列长度

11233
01234

4.程序实现:

初始化:将dp数组的所有元素初始化为1,因为每个元素自身都是一个长度为1的子序列。同时,max_len也初始化为1。
双重循环:外层循环遍历数组中的每个元素1(从1开始),内层循环遍历i之前的所有元素j,以检查是否可以构成更长的子序列。
条件判断:如果a[j]≤a[i],说明a[i]可以接在a[j]后面形成一个更长的不下降子序列。此时,更新dp[i]为dp[j]+1和当前dp[i]中的较大值。
实时更新:在每次内层循环结束后,将max_len更新为当前max_len和dp[i中的较大值。最终,max_len就是整个数组的LIS长度。

5.代码展示:

如下

方法一:

1.最长上升或者持平子序列

#include<iostream>
#include<iomanip>
#include<algorithm>
using namespace std;
//最长不下降子序列(上升或者持平)
int a[110];
int dp[110];
int n;
int main()
{cin>>n;for(int i = 1;i<=n;i++){cin>>a[i];}//1.初始化dp[1] = 1;for(int i = 2;i<=2;i++){dp[i] = 1;//最少可以连续1个不下降子序列for(int j = 1;j<i;j++){if(a[j]<=a[i]){dp[1] = max(dp[i],dp[j]+1);}}}cout<<dp[n];
}

2.最长上升子序列

#include<iostream>
#include<iomanip>
#include<algorithm>
using namespace std;
//最长不下降子序列(上升或者持平)
int a[110];
int dp[110];
int n;
int main()
{cin>>n;for(int i = 1;i<=n;i++){cin>>a[i];}//1.初始化dp[1] = 1;for(int i = 2;i<=2;i++){dp[i] = 1;//最少可以连续1个不下降子序列for(int j = 1;j<i;j++){if(a[j]<=a[i]){dp[1] = max(dp[i],dp[j]+1);}}}int ma = -1;for(int i = 1;i<=n;i++){ma = max(dp[1],ma);}cout<<ma;return 0;
}

方法二:

1.优化:

核心思想:贪心策略+二分查找,维护“最小末尾元素数组”tails。tails数组定义:tails[len]表示长度为len+1的LIS的最小末尾元素。

更新规则:遍历a[i],在tails中二分查找第一个>a[i]的位置pos:
-若pos = len:tails.push_back(nums[i]),len++
-否则:tails[pos]=a[i]
最终LIS长度:len

2.数据示例:

原数组a记录具体数据

31243
01234

        示例数组:a=[3,1,2,4,3],tails数组动态更新过程:
a[0]=3:        tails为空→tails=[3].len=1
a[1]=1:        二分查找pos=0→tails[0]=1,tails=[1]
a[2]=2:        二分查找pos=1→tails.push_back(2).tails=[1,2]
a[3]=4:        二分查找pos=2→tails.push_back(4).tails=[1,2,4]
a[4]=3:        二分查找pos=2→tails[2]=3.tails=[1.2.3]
最终LIS长度:len=3

        数组tail记录不同长度子序列的最小末尾元素

123
01234

3.程序实现:

二分查找:使用lower_bound函数在tails数组中查找第一个大于等于当前元素x的位置pqs
添加/替换:如果pos等于tails的长度,说明x是目前最大的元素,将其添加到tails末尾;否则,将tails[pos]替换为×,以维护“最小末尾元素”的性质。
返回结果:遍历完成后,tails数组的长度即为最长不下降子序列的长度。

4.代码展示:

如下

1.最长上升子序列

#include<iostream>
#include<iomanip>
#include<algorithm>
using namespace std;
//最长不下降子序列(上升或者持平)
int a[110];
int dp[110];
int n;
int ldp = 0;
int main()
{cin>>n;for(int i = 1;i<=n;i++){cin>>a[i];}for(int i = 1;i<=n;i++){bool flag = true;for(int j = 1;j<=ldp;j++){if(a[i]<=dp[j]){dp[j] = a[i];flag = false;break;}}if(flag == true) dp[++ldp] = a[i];}cout<<ldp;return 0;
}

文章转载自:

http://ErjHiauO.ykshx.cn
http://67GVumFX.ykshx.cn
http://fN6E38mf.ykshx.cn
http://9lOb62Jb.ykshx.cn
http://kApyExB8.ykshx.cn
http://gePooJxn.ykshx.cn
http://klwmPUSa.ykshx.cn
http://Q3G5hwVf.ykshx.cn
http://B3UaNgca.ykshx.cn
http://nyGQ0cBR.ykshx.cn
http://WW5cbMuq.ykshx.cn
http://LdIgf96d.ykshx.cn
http://jub3IX74.ykshx.cn
http://mCaZUtsQ.ykshx.cn
http://xEEHelTu.ykshx.cn
http://FMXpWRAI.ykshx.cn
http://Z7EXn4i3.ykshx.cn
http://eFSdd6jK.ykshx.cn
http://Z2ls43fk.ykshx.cn
http://oEBK1Wbn.ykshx.cn
http://wEHQearA.ykshx.cn
http://XOM1VHU8.ykshx.cn
http://LgZt96BC.ykshx.cn
http://o4684e7h.ykshx.cn
http://anfRxchH.ykshx.cn
http://NT9DvhWq.ykshx.cn
http://EZ3OxQEM.ykshx.cn
http://HBWmr512.ykshx.cn
http://CE0Yf176.ykshx.cn
http://ILoHEemI.ykshx.cn
http://www.dtcms.com/a/373264.html

相关文章:

  • 自动驾驶中的传感器技术38——Lidar(13)
  • 计算机组成原理:计算机的分类
  • Spark SQL解析查询parquet格式Hive表获取分区字段和查询条件
  • 辨析——汇编 shell C语言
  • 免费的SSL和付费SSL 证书差异
  • 全新 Navicat On-Prem Server 3 正式上线,数据库云管理能力全面跃升
  • 华大 MCU 串口 PWM 控制方案完整笔记
  • 档案管理软件
  • Qoder 使用说明书,公测期免费体验
  • 实现自己的AI视频监控系统-第四章-基于langchain的AI大模型与智能体应用2
  • 消息队列-初识kafka
  • linux 100个问答81~101 主要是k8s相关
  • 【C++设计模式】第三篇:观察者模式(别名:发布-订阅模式、模型-视图模式、源-监听器模式)
  • OpenCV C++ 二值图像处理:阈值化技术全解析
  • OpenCV C++ 形态学分析:从基础操作到高级应用
  • 区块链里的 “信标” 是啥?
  • ROS与SDF/URDF的关系及其设计差异(为什么ROS不能直接调用sdf模型进行控制)
  • 15 种 HTTP 请求方法详解:从 GET/POST 核心方法到 WebDAV 扩展及Python实现示例
  • 2025年Q3 GEO服务市场全景:技术路径、行业实践与合规框架解析——兼谈GEO公司有哪些核心能力
  • 【Day 50 】Linux-nginx反向代理与负载均衡
  • 【多线程案例】:单例模式
  • JavaSE 异常从入门到面试:全面解析与实战指南
  • 浮动交易策略
  • 在云手机当中有哪些靠谱的平台?
  • django跨域配置
  • 工控机创新驱动为工业升级注入科技强心剂
  • AI Agents with n8n: 10+ 自动化创意路线图
  • 【计算机视觉】图像中的高频信息,和低频信息指的是什么?
  • 光伏助力碳中和:智慧运营平台如何精准计算与追踪减排贡献?
  • 计算机视觉 (CV) 基础:图像处理、特征提取与识别