最长上升子序列(LIS)简介及其例题分析

news2024/11/16 9:29:50

一.最长上升子序列(LIS)的相关知识

1.最长上升子序列(Longest  Increasing Subsequence),简称LIS,也有些情况求的是最长非降序子序列,二者区别就是序列中是否可以有相等的数。假设我们有一个序列 b i,当b1 < b2 < … < bS的时候,我们称这个序列是上升的。

(或许我们刚开始对于这样的名词感到陌生,对于解释也不理解,那我们就要知道它的前置知识)

 一.什么是子序列?

    一个序列A={a1,a2,...an}中任意删除若干项,剩余的序列叫做A的一个子序列。例如序列A={1,3,5,4,2},删除其中的第3项和第5项,得到序列B={1,3,4},删除其中的第3项和第4项,得到序列C={1,3,2},此时序列B和C是序列A的子序列。

二.什么是最长子序列?

    如果序列中的元素是从小到大排列的,则该序列为上升序列,如果该序列又是其它序列的子序列,则称为上升子序列。例如“1.1 子序列”中提到的B是A的上升子序列,而C是A的子序列,但不是上升子序列。

了解这两个前置知识,那么最长上升子序列就很容易理解了。

即包含元素最多的上升子序列,叫做最长上升子序列。

 

 二.LIS长度的求解方法

一.方法一:动态规划(O(n^2)朴素法)

动态规划的一个特点就是当前解可以由上一个阶段的解推出, 由此,把我们要求的问题简化成一个更小的子问题。我们求最长上升子序列也符合这一特点,我们要求前n个数的最长上升子序列就是可以转换成求前n-1个数的最长上升子序列......这样逐步分解,直到求前1个数的最长上升子序列。

状态转移方程为:dp[i]=max(dp[i],dp[j]+1)

其核心代码段为:

for (int i = 1; i <= n; i++) {
		for (int j = 1; j < i; j++) {
			if (a[i] > a[j])
				dp[i] = max(dp[i], dp[j] + 1);
		}
	}
	for (int i = 1; i <= n; i++) {
		ans = max(ans, dp[i]);
	}


 

二.方法二:贪心+二分(O(nlogn))

用一个low数组记录长度,low[i]表示长度都为i的LIS结尾元素的最小值,这样我们在记录low的时候,当a[i]大于low[++当前LIS最大长度]时候,直接将a[i]接在low中,否则在low中二分查找大于等于当前元素a[i]的第一个位置pos,用a[i]替换掉之前的low[pos].最后我们找一下最长上升子序列下标满足的解,记录下该子序列即可.(注意,low数组不一定是最长上升子序列,只是长度对等)

这里的二分操作可以用STL中的lower_bound()函数实现。

核心代码段:

low[++sum]=a[1];
for (int i = 2; i <= n; i++) {
	if (a[i] > low[sum])
		low[++sum] = a[i];
	else
	{
		int k = lower_bound(low + 1, low + sum + 1, a[i]) - dp;
		low[k] = a[i];
	}
}

 

三.例题分析

 一.B3637 最长上升子序列

 

 这一题就相当于最长上升子序列的模版题,通过动态规划(朴素法)就可以解决,这里可以当做模版学习。

#include<bits/stdc++.h>
using namespace std;
#define N 1000005
int dp[N], a[N];
int ans, n, m, sum;
int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		dp[i] = 1;           //初始化,dp都为1,即自身是一个上升子序列
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j < i; j++) {  //如果在之前的序列有小于a[i]的,更新dp
			if (a[i] > a[j])
				dp[i] = max(dp[i], dp[j] + 1);
		}
	}
	for (int i = 1; i <= n; i++) {
		ans = max(ans, dp[i]);   //找出最长的上升子序列
	}
	cout << ans << endl;
	return 0;
}

二.LIS

这一题和刚刚的题目的意思是一模一样的,唯一的区别就是数据范围变大了,变为1e5,如果我们还是和刚刚一样使用O(n^2)的方法,肯定会超时,那么我们就应该使用方法二:贪心+二分       (O(nlogn))

#include<bits/stdc++.h>
using namespace std;
#define N 100005
int a[N], b[N];
int n, m, sum, ans;
int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	b[++sum] = a[1];     //核心代码段,没什么好说的
	for (int i = 2; i <= n; i++) {
		if (a[i] > b[sum])
			b[++sum] = a[i];
		else
		{
			int k = lower_bound(b + 1, b + sum + 1, a[i]) - b;
			b[k] = a[i];
		}
	}
	cout << sum << endl;
	return 0;
}

这里给大家留下两道练习题,这两道题都是在此基础上的变形题,可以会有点难(都是洛谷上的题,可以看题解),后面我也会给出分析。

[ARC149B] Two LIS Sum

P8736 [蓝桥杯 2020 国 B] 游园安排

另外,关于LIS还有一个姊妹叫作LCS(最长公共上上子序列),下次我们将讲解相关内容,好了今天的内容就到这里了。~QVQ~

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

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

相关文章

[数据结构]栈

1.栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出的原则。 压栈&#xff1a;栈的插入操作叫做进栈/压栈/入栈&#…

【UEFI实战】BIOS中的openssl

BIOS中的openssl openssl是一个密码库或者密码工具&#xff0c;在密码学基础_hex string is too short, padding with zero bytes t-CSDN博客介绍了基本的密码学概念已经openssl工具的使用&#xff0c;而这里将介绍BIOS下如何使用openssl。 在开源的BIOS代码库EDK中包含一个C…

数据结构作业复盘1:字符串疑难杂症小汇总(字符串赋值,指针数组...)

学校里开始上数据结构了&#xff0c;一开始是从C语言一些相关的基础开始讲起。第一次作业主要是字符串相关的基础知识以及编程题目。先做了一部分&#xff0c;整理了一下一些字符串隐含的知识和一些易误易混的概念&#xff0c;算是给自己的一个复盘和归纳。 strcpy函数相关 首…

Linux系统编程之多线程

目录 1、进程与线程 2、线程的优势与使用理由 3、多线程的使用 3.1 线程的使用 1.线程创建函数 2.线程退出函数 3.线程的等待 4.线程脱离 5. 线程ID获取及比较 6.示例 3.2 互斥锁的应用 1.互斥锁相关API 2.示例 3.3 条件变量的使用 1. 创建及销毁条件变量 2. 等待…

数字化转型导师坚鹏:证券公司数字化领导力提升之道

证券公司数字化领导力提升之道 ——融合中西智慧&#xff0c;践行知行合一思想&#xff0c;实现知行果合一 课程背景&#xff1a; 很多证券公司存在以下问题&#xff1a; 不知道证券公司数字化思维如何提升&#xff1f; 不清楚证券公司数字化领导力模型内涵&#xff1f;…

加密与安全_探索数字证书

文章目录 Pre概述使用keytool生成证书使用Openssl生成证书 &#xff08;推荐&#xff09;证书的吊销小结 Pre PKI - 借助Nginx 实现Https 服务端单向认证、服务端客户端双向认证 PKI - 04 证书授权颁发机构&#xff08;CA&#xff09; & 数字证书 PKI - 数字签名与数字证…

土壤侵蚀量化评估

根据之前的文章,已经算出了R、K、LS、C、P 现在计算土壤侵蚀,将几个前期制作好的因子的TIFF文件,用栅格计算器相乘 发现局部地区存在轻度侵蚀,大部分区域是微度侵蚀 然后对比了一下范围 其中的几个因子都在文献范围内,说明计算结果并未出错,可能就是研究区正常范围和结…

《数字图像处理(MATLAB版)》相关算法代码及其分析(1)

目录 1 自适应中值滤波算法 1.1 函数定义 1.2 输入参数检查 1.3 初始化 1.4 自适应中值滤波过程 1.5 处理剩余未处理的像素 1.6 总结 2 计算输入数组的平均值 2.1 函数定义 2.2 注释 2.3 输入验证 2.4 计算平均值 2.5 总结 3 基于高斯模型的贝叶斯分类器 3.1 函…

【搭建 Hbase 集群】

搭建 Hbase 集群 一、准备工作二、三台服务器之间的 SSH 免密登录1.修改hosts文件添加DNS映射2.在每台服务器上生成 SSH 密钥对3.将公共密钥&#xff08;通常为 ~/.ssh/id_rsa.pub&#xff09;复制到目标服务器上4.从本地使用 SSH 命令无需密码连接到目标服务器 二、安装JDK1.执…

Linux/Docker 修改系统时区

目录 1. Linux 系统1.1 通过 timedatectl 命令操作1.2 直接修改 /etc/localtime 文件 2. Docker 容器中的 Linux 操作环境&#xff1a; CentOS / AlmaOSMySQL Docker 镜像 1. Linux 系统 1.1 通过 timedatectl 命令操作 使用 timedatectl list-timezones 命令列出可用的时区…

Learning from Unlabeled 3D Environments forVision-and-Language Navigation

这篇论文是关于高级指令的 摘要 在视觉和语言导航 (VLN) 中&#xff0c;实体代理需要按照自然语言指令在真实的 3D 环境中进行导航。现有 VLN 方法的一个主要瓶颈是缺乏足够的训练数据&#xff0c;导致对未见过的环境的泛化效果不理想。虽然 VLN 数据通常是手动收集的&#x…

2024年 前端JavaScript Web APIs 第一天 笔记

1.1 -声明变量const优先 1.2 -DOM树和DOM对象 1.3 -获取DOIM元素 1.4 -DOM修改元素内容以及年会抽奖 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content&quo…

初识面相对象深入理解、构造方法--学习JavaEE的day12

day12 一、初识面相对象深入理解 需求&#xff1a; 创建人类的对象&#xff0c;并操作对象 分析&#xff1a; 人类 - Person 属性&#xff1a;name、sex、age 方法&#xff1a;eat、sleep 场景&#xff1a;创建多个对象&#xff0c;去操作对象 public class Person {//成员变…

9、taocms代码审计

一、XSS 1、DOM型xss 限制 无复现 payload: aa)alert(1)( 触发的参数&#xff1a;name代码 根据路由找到对应的文件&#xff0c;在api.php里接受全局变量action&#xff0c;最终赋值给$m,判断 如果$m不在数组就结束&#xff0c;新建方法复制给$model。检查类的方法是否存…

2024 年广东省职业院校技能大赛(高职组)“云计算应用”赛项样题 2

#需要资源或有问题的&#xff0c;可私博主&#xff01;&#xff01;&#xff01; #需要资源或有问题的&#xff0c;可私博主&#xff01;&#xff01;&#xff01; #需要资源或有问题的&#xff0c;可私博主&#xff01;&#xff01;&#xff01; 某企业根据自身业务需求&#…

【全局异常处理记录】⭐️通过自定义全局处理器有效统一各种异常并记录

目录 前言 方案 示例 测试 总结 前言 朋友们大家好啊&#xff0c;随着项目的进行&#xff0c;接口也是越来越多了&#xff0c;每个接口无论调用成功与否&#xff0c;都要有相应的应对措施&#xff0c;总不能出错的时候返回一堆异常信息给调用者&#xff0c;所以每个接口都…

Python算法100例-3.2 水仙花数

完整源代码项目地址&#xff0c;关注博主私信源代码后可获取 1.问题描述2.问题分析3.算法设计4.确定程序框架5.完整的程序6.问题拓展7.巧用字符串技巧 1&#xff0e;问题描述 输出所有的“水仙花数”。所谓的“水仙花数”是指一个三位数&#xff0c;其各位数字的立方和等于该…

【机器学习】有监督学习算法之:支持向量机

支持向量机 1、引言2、决策树2.1 定义2.2 原理2.3 实现方式2.4 算法公式2.5 代码示例 3、总结 1、引言 小屌丝&#xff1a;鱼哥&#xff0c;泡澡啊。 小鱼&#xff1a;不去 小屌丝&#xff1a;… 此话当真&#xff1f; 小鱼&#xff1a;此话不假 小屌丝&#xff1a;到底去还是…

奔跑吧,前端er!前端五大方向技能罗列,webGL、AI、桌面、游戏

经常看到头条上前端们争论各种框架的优劣&#xff0c;然后相互争吵不休&#xff0c;其实技术也好&#xff0c;框架也好&#xff0c;都是服务于项目需求的&#xff0c;争论的铁子们都站在自己的项目角度来品评工具&#xff0c;肯定是公说公有理婆说婆有理啦。 技术和框架是中性的…

ArrayBlockingQueue 数组阻塞队列 源码阅读

1. 概述 数组阻塞队列 有界的阻塞数组, 容量一旦创建, 无法修改阻塞队列, 队列满的时候, 往队列put数据会被阻塞, 队列空, 取数据也会被阻塞并发安全 2. 数据结构 /** 存储队列元素的数组 */ /** 存储队列元素的数组 */ final Object[] items;/** 队首位置&#xff0c;下一…