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

一.最长上升子序列(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]的,更新dpif (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.mzph.cn/news/717833.shtml

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

相关文章

【论文笔记】Initializing Models with Larger Ones

Abstract 介绍权重选择&#xff0c;一种通过从预训练模型的较大模型中选择权重子集来初始化较小模型的方法。这使得知识从预训练的权重转移到更小的模型。 它还可以与知识蒸馏一起使用。 权重选择提供了一种在资源受限的环境中利用预训练模型力量的新方法&#xff0c;希望能够…

【Linux】软件管理yum | 编辑器vim | vim插件安装

目录 1. Linux软件管理yum 1.1 什么是软件包 1.2 查看软件包 1.3 如何安装软件 1.4 如何卸载软件 2. Linux编辑器vim 2.1 vim的基本概念 2.2 vim的基本操作 2.3 vim正常模式命令集 2.4 vim末行模式命令集 2.5 简单vim配置 2.6 插件安装 1. Vim-Plug 3. coc.nvim …

如何自己系统的学python

学习Python是一项很好的投资&#xff0c;因为它是一种既强大又易于学习的编程语言&#xff0c;适用于多种应用&#xff0c;如数据分析、人工智能、网站开发等。下面是一个系统学习Python的步骤建议&#xff1a; 基础准备 安装Python&#xff1a; 访问Python官网下载最新版本的…

微信小程序-生命周期

页面生命周期 onLoad: 页面加载时触发的方法&#xff0c;在这个方法中可以进行页面初始化的操作&#xff0c;如获取数据、设置页面状态等。 onShow: 页面显示时触发的方法&#xff0c;在用户进入页面或从其他页面返回该页面时会调用此方法。可以在此方法中进行页面数据刷新、动…

Onenote软件新建笔记本时报错:无法在以下位置新建笔记本

报错现象&#xff1a; 当在OneNote软件上&#xff0c;新建笔记本时&#xff1a; 然后&#xff0c;尝试重新登录微软账户&#xff0c;也不行&#xff0c;提示报错&#xff1a; 解决办法&#xff1a; 打开一个新的记事本&#xff0c;复制粘贴以下内容&#xff1a; C:\Users\Adm…

Mysql中的事务

什么是事务&#xff1a; 多条sql语句&#xff0c;要么全部成功&#xff0c;要么全部失败。 事务的特性&#xff1a; 1&#xff1a;原子性(Atomic)&#xff1a; 组成一个事务的多个数据库操作是一个不可分割的原子单元&#xff0c;只有所有操作都成功&#xff0c;整个事务才会…

C++调用lua函数

C 调用Lua全局变量(普通) lua_getglobal(lua, "width");int width lua_tointeger(lua,-1);lua_pop(lua,1);std::cout << width << std::endl;lua_close(lua); 这几行代码要放到lua_pcall(lua, 0,0,0);之后才可以. C给lua传递变量 lua_pushstring(lua, …

Python 操作 Excel,如何又快又好?

➤数据处理是 Python 的一大应用场景&#xff0c;而 Excel 则是最流行的数据处理软件。因此用 Python 进行数据相关的工作时&#xff0c;难免要和 Excel 打交道。Python处理Excel 常用的系列库有&#xff1a;xlrd、xlwt、xlutils、openpyxl ◈xlrd &#xff0d; 用于读取 Exce…

Rocky 9 安装 R-CytoTRACE

官网给出的详细指南&#xff0c;只是可能大家打不开或者懒得去看E文。 第一步&#xff0c;下载CytoTRACE安装包。 wget https://cytotrace.stanford.edu/CytoTRACE_0.3.3.tar.gz 第二步&#xff0c;打开R或者Rstudio-server # 安装依赖包 if (!requireNamespace("Bioc…

视频云平台——搭建SRS5平台支持GB28181视频流的推送

&#x1f4e2;欢迎点赞 &#xff1a;&#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff0c;赐人玫瑰&#xff0c;手留余香&#xff01;&#x1f4e2;本文作者&#xff1a;由webmote 原创&#x1f4e2;作者格言&#xff1a;新的征程&#xff0c;我们面对的不仅…

谨用ArrayList中的subList方法

谨用ArrayList中的subList方法 规范一&#xff1a; ArrayList 的 subList 结果不可强转成 ArrayList&#xff0c;否则会抛出 ClassCastException 异常&#xff1a; public static void test7() {List<Integer> list new ArrayList<>();list.add(1);list.add(2);…

JavaWeb—— SpringBootWeb综合案例(登录功能、登录校验、异常处理)

案例-登录认证 目录 案例-登录认证1. 登录功能1.1 需求1.2 接口文档1.3 思路分析1.4 功能开发1.5 测试 2. 登录校验2.1 问题分析2.2 会话技术2.2.1 会话技术介绍2.2.2 会话跟踪方案2.2.2.1 方案一 - Cookie2.2.2.2 方案二 - Session2.2.2.3 方案三 - 令牌技术 2.3 JWT令牌2.3.1…

程序员眼中的“祖传代码”

引言 在IT界&#xff0c;特别是在Java项目中&#xff0c;“祖传代码”通常指的是那些经过长时间积累、由多位开发者共同维护、且蕴含深厚技术沉淀的代码片段或模块。这些代码可能存在于项目的核心模块&#xff0c;也可能是一些辅助性的工具类。它们承载着项目的历史&#xff0…

Matlab 多项式插值(曲线拟合)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 由于对曲线拟合有些兴趣,这里就找了一些资料从最基本的方法来看一下曲线拟合的效果: 二、实现代码 % **********

python科学计算库之Numpy库的使用的简单习题

Numpy库 Numpy&#xff08;Numerical Python的缩写&#xff09;是一个开源的Python库&#xff0c;用于进行科学计算。它提供了一个高性能的多维数组对象&#xff08;ndarray&#xff09;及用于处理这些数组的各种工具和函数。由于其高效和灵活的数据结构以及丰富的功能&#x…

Google 地图 API 教程--干货(1/2)

Google Maps API 教程 在本教程中我们将学习如何使用谷歌地图API V3创建交互式地图。 什么是 API? API = 应用程序编程接口(Application programming interface)。 API(Application Programming Interface,应用编程接口)其实就是操作系统留给应用程序的一个调用接口,…

案例介绍:汽车售后服务网络构建与信息抽取技术应用(开源)

一、引言 在当今竞争激烈的汽车行业中&#xff0c;售后服务的质量已成为品牌成功的关键因素之一。作为一位经验丰富的项目经理&#xff0c;我曾参与构建一个全面的汽车售后服务网络&#xff0c;旨在为客户提供无缝的维修、保养和配件更换服务。这个项目的核心目标是通过高效的…

状态机实现双击、短按、长按等按键识别检测算法

1、按键识别算法的作用 按键识别算法在不同的技术和应用背景下有不同的作用&#xff0c;但其核心目标都是准确、可靠地检测和区分用户通过物理或虚拟按键所执行的操作。按键识别算法在各类电子设备及系统中起到至关重要的作用&#xff0c;它确保了人机交互的有效性和准确性&…

Vue前端+快速入门【详解】

目录 1.Vue概述 2. 快速入门 3. Vue指令 4.表格信息案例 5. 生命周期 1.Vue概述 1.MVVM思想 原始HTMLCSSJavaScript开发存在的问题&#xff1a;操作麻烦&#xff0c;耦合性强 为了实现html标签与数据的解耦&#xff0c;前端开发中提供了MVVM思想&#xff1a;即Model-Vi…

Mysql-主从架构篇(一主多从,半同步案例搭建)

主从架构 主从架构有什么用&#xff1f; 通过搭建MySQL主从集群&#xff0c;可以缓解MySQL的数据存储以及访问的压力。 数据安全&#xff08;主备&#xff09;&#xff1a;给主服务增加一个数据备份。基于这个目的&#xff0c;可以搭建主从架构&#xff0c;或者也可以基于主…