最长递增子序列(LIS)

23 篇文章 8 订阅
订阅专栏

最长递增子序列(LIS)

问题描述:

求一个序列的最长递增子序列,这样的子序列是允许中间越过一些字符的,即留“空”。

例如:4 2 3 1 5 的最长递增子序列为 2 3 5,长度为 3 。

解法:

这里给出两种动态规划的做法,第二种是比较优化的 dp 。

① dp:dp[i] 表示以 i 结尾的最长递增子序列长度
在这里插入图片描述
第一个元素直接设置 LIS 长度为 1 即可。
在这里插入图片描述
处理第二个元素 2 的时候判断是否比前面的元素 4 大,没有的话那么以 2 为结尾的 LIS 就是 2,

即 LIS 长度为 1。
在这里插入图片描述
处理第三个元素 3 的时候需要跟前面的每个元素都进行比较,3 大于 2,则 LIS 的长度可能为 dp[1] + 1,

3 小于 4,则 LIS 的长度可能为 1,比较dp[1] + 1 和 1,取最大值,为 2 。
在这里插入图片描述
处理第四个元素 1,发现比前面的元素都小,那么以 1 为结尾的 LIS 只可能为 1,因此 LIS 的长度为 1。
在这里插入图片描述
处理最后一个元素 5,发现比前面的元素都大,那么以 5 结尾的 LIS 的长度可能为

dp[0] + 1,dp[1] + 1,dp[2] + 1,dp[3] + 1。

其中的最大值为 dp[2] + 1 = 3,因此 LIS 的长度为 3。

总结:

dp[i] 默认都为 1,因为以 i 结尾的 LIS 至少包含自己。

在 dp 表 0~i-1 中比对时,若 arr[i] > arr[j],

那么 dp[j] + 1 可能为 dp[i] 的最终值。

需要在所有的可能值中取最大值。

时间复杂度为 O(n2)。

② dp:dp[i] 表示长度为 i 的最长递增子序列(LIS)末尾的数
在这里插入图片描述
第一个元素直接加入 dp 表,dp[1] = 4,表示长度为 1 的 LIS 末尾的数当前为 4。
在这里插入图片描述
第二个元素为 2,因为 2 < 4,直接替换掉 4,dp[1] = 2 。

因为后面序列中的数字 > 2 的几率一定比 > 4 的几率高,有种贪心的感觉。
在这里插入图片描述
第三个元素为 3,由于 3 > dp[1] = 2,构成递增,dp[2] = 3,表示长度为 2 的 LIS 的末尾为 3 。
在这里插入图片描述
第四个元素为 1,由于 1 < dp[2] = 3,因此在前面一定有一个位置可以换成 1,

并且后面的递增性质不会被破坏。

第一个 > 1 的为 dp[1] = 2,因此将 dp[1] 置为 1。
在这里插入图片描述
最后一个元素为 5, 5 > dp[2] = 3,构成递归,故dp[3] = 5。

全部遍历完成,这个时候我们就可以发现 dp 数组的下标 3 就是我们要求的 LIS 长度。

参考代码:

// 这里的最长递增子序列是允许中间跨越其他子序列的 
#include<iostream>
#include<algorithm>
using namespace std;

int *arr;
int *dp;

// 经典问题 dp[i]的意思为以i为结尾的最长子序列为多少 
int getResult(int n)
{
	dp[0] = 1;
	for (int i = 1; i < n; i++)
	{
		int cnt = 1;
		for (int j = i - 1; j >= 0; j--)
		{
			if (arr[i] > arr[j])
			{  // 保证递增 
				cnt = max(cnt, dp[j] + 1);
			}
		}
		dp[i] = cnt;
	}
	int ans = 0;
	for (int i = 0; i < n; i++)
	{
		ans = max(ans, dp[i]);
	}
	return ans;
}

// 二分查找变体 找到第一个大于等于n的位置index 
int BinarySearch(int *dp, int len, int n)
{
	int left = 1;
	int right = len;
	while (left < right)
	{
		int mid = (left + right) / 2;
		if (dp[mid] >= n)
		{
			right = mid;
		}
		else
		{
			left = mid+1;
		}
	}
	return right;
}

// 优化的dp dp数组的最终下标为答案 
int getResult1(int n)
{
	 dp[1] = arr[0];
	 int index = 1;
	 for (int i = 1; i < n; i++)
	 {
	 	if (arr[i] > dp[index])
	 	{
	 		// 更新index 
	 		dp[++index] = arr[i];
		 }
		 else
		 {
		 	// 把dp数组中第一个大于等于n的数字替换为arr[i] 
		 	int tempIndex = BinarySearch(dp, index, arr[i]);
		 	dp[tempIndex] = arr[i];
		 }
	 }
	 return index;
} 

int main(){
	int n;
	while (cin >> n)
	{
		arr = new int[n];
		dp = new int[n+1]; 
		for (int i = 0; i < n; i++)
		{
			cin >> arr[i];
		}
		int ans = getResult1(n);
		cout << ans << endl;
		delete[] arr;
		delete[] dp;
	}
	return 0;
} 

【END】感谢观看

最长递增子序列
切梦
07-29 4475
问题 给定一个长度为N的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱)。例如:给定一个长度为6的数组A{5, 6, 7, 1, 2, 8},则其最长的单调递增子序列为{5,6,7,8},长度为4. 解法1:最长公共子序列法 这个问题可以转换为最长公共子序列问题。如例子中的数组A{5,6, 7, 1, 2, 8},则我们排序该数组得到数组A‘{1, 2, 5, 6, 7,...
图解:什么是最长递增子序列
Z景明的博客
11-26 7390
最长递增子序列 普通动态规划问题解题四步骤 (涉及最优子结构和重叠子问题)基于状态压缩的动态规划解题步骤0-1背包问题在之前的文章中,我已经给大家介绍过了动态规划的常见类型、解题步骤,以...
动态规划:最长单调递增子序列
05-28
动态规划:最长单调递增子序列 A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ..., aN) be any sequence (ai1, ai2, ..., aiK), where 1 <= i1 < i2 < ... < iK <= N. For example, sequence (1, 7, 3, 5, 9, 4, 8) has ordered subsequences, e. g., (1, 7), (3, 4, 8) and many others. All longest ordered subsequences are of length 4, e. g., (1, 3, 5, 8). Your program, when given the numeric sequence, must find the length of its longest ordered subsequence.
LIS 最长递增子序列 Java的简单实现
09-01
下面小编就为大家带来一篇LIS 最长递增子序列 Java的简单实现。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
JavaScript 最长递增子序列
最新发布
weixin_47032028的博客
05-07 213
因为Vue3的原因,最长递增子序列在前端圈火了。身为菜鸟的我第一次听到这个词的时候,脑袋都懵了,这是个啥玩意儿?最长递增子序列(longest increasing subsequence)问题是指,在一个给定的数值序列中,找到一个子序列,使得这个子序列元素的数值依次递增,并且这个子序列的长度尽可能地大。最长递增子序列中的元素在原序列中不一定是连续的。例如,在给定数组 [4, 5, 1, 2, 7, 3, 6, 9, 0] 中,最长递增子序列是 1,2,3,6,9。
最长递增子序列(LIS longest-increment-subsequence)最长连续递增子序列 最大连续子序列和
bitcarmanlee的博客
03-27 821
1.问题描述 给定一个数组,就数组最长递增子序列(子序列可以不连续) 2.解法 非常经典的动态规划问题,算法的时间复杂为O(n^2),空间复杂度为O(n)。 关键是结果数组dp[i]怎么计算呢? 每次遍历所有j<i中数组的元素,判断array[j]是否小于array[i]。 如果是,检查dp[i]与dp[j]+1的大小,并且更新dp[i]。 public static int lis...
LIS-最长递增子序列
某科学的程序员
07-24 491
最长递增子序列是指在一个给定的数值序列中,找到一个子序列,使得这个子序列元素的数值依次递增,并且这个子序列的长度尽可能地大,注意子序列中的元素在原序列中不一定是连续的 。
一文读懂最长递增子序列LIS
qq_29924317的博客
05-24 95
/ dp[i]表示戳破气球i后,左右剩余气球可以获得的最大硬币数。// dp[i]表示将前i个元素划分为一部分的最大和。// 戳破气球i,左右可以获得的最大硬币数加上当前气球价值的最大值。// dp[i]表示以信封i结尾的LIS长度。// 枚举区间[0, i]内的最大值。// 如果找不到,len增加1。// dp[i]取决于dp[j-1]加上区间[j, i]的和。// 更新dp[i]// 二分查找第一个大于等于envelope[1]的dp[i]// 线段树,interval[i]表示i号节点管理的区间。
最长递增子序列问题(你真的会了吗)
qq_56999918的博客
07-03 8740
1.对应牛客网链接2.题目描述: 3.解题思路下面以[5,7,1,9,4,6,2,8,3]为例:4.对应代码:1.对应牛客网链接:2.题目描述: 3.解题思路:4.对应代码:1.对应letecode链接:2.题目描述:3.解题思路4.对应代码:...
如何给dropdownlist动态赋初始值_动态规划设计方法:归纳思想解决 LIS
weixin_39619635的博客
11-24 394
读完本文,你可以去力扣拿下如下题目:300.最长上升子序列-----------也许有读者看了前文 动态规划详解,学会了动态规划的套路:找到了问题的「状态」,明确了 dp 数组/函数的含义,定义了 base case;但是不知道如何确定「选择」,也就是不到状态转移的关系,依然写不出动态规划解法,怎么办?不要担心,动态规划的难点本来就在于寻找正确的状态转移方程,本文就借助经典的「最长递增子序列问题」...
leetcode:300. 最长递增子序列
OceanStar的博客
05-11 2558
题目来源 leetcode:300. longest-increasing-subsequence最长递增子序列 题目描述 题目解析 题意: 需要对「子序列」和「子串」这两个概念进行区分; 子序列(subsequence):子序列并不要求连续,例如:序列 [4, 6, 5] 是 [1, 2, 4, 3, 7, 6, 5] 的一个子序列; 子串(substring、subarray):子串一定是原始字符串的连续子串 题目中的「上升」的意思是「严格上升」。反例: [1, 2, 2, 3] 不能算作
最长上升子序列(LIS
Prime_siri的博客
08-26 203
题目描述 设有由n个不相同的整数组成的数列,记为:b[1], b[2], ... , b[n], 且b[i]<>b[j](i<>j),若存在i[1] < i[2] < i[3] < ... <i[n’],且有b[i[1]] < b[i[2]] < ... <b[i[n’]],则称数列为长度为n’的上升子序列。程序要求,当原数列给出后,求出最长的上升子序列。 例如13,7,9,16,38,24,37,18,44...
求数组中最长递增子序列的解决方法
09-05
在计算机科学中,数组是最长递增子序列(Longest Increasing Subsequence,LIS)问题是一个经典的动态规划问题。此问题旨在找出一个给定数组中,所有递增子序列中最长的那个。在C++中,我们可以采用两种不同的方法来...
C语言实现最长递增子序列问题的解决方法
09-04
最长递增子序列(Longest Increasing Subsequence, LIS)问题是计算机科学中的一种经典算法问题,主要涉及序列处理和动态规划。在给定的序列中,目标是找到一个尽可能长的子序列,使得这个子序列中的元素是严格递增...
最长单调递增子序列LIS
09-11
我写的LIS算法,有两种思路,程序全在这个cpp文件中,可以运行
最长递增子序列1
08-08
最长递增子序列LIS)是数组或序列中一个重要的概念,它的目标是找到一个序列的最长子序列,使得这个子序列中的元素是严格递增的。在给定的描述中,我们看到了三种不同的方法来求解LIS问题。 **方法一:动态规划...
数据结构与算法之最长递增子序列
weixin_47225948的博客
09-20 1133
数据结构与算法之最长递增子序列
最长递增子序列LIS)的三种算法
Irimsky
08-16 3878
最长递增子序列:给定一个长度为N的数组,找出一个最长的单调递增子序列,子序列不一定连续,但初始顺序不能乱。 比如数组A={1,3,4,2,5},其最长递增子序列为1,3,4,5 方法一:最长公共子序列法 对于给定长度为N的数组A: 使数组B为排序后的数组A (O(NlogN)) 求出A与B的最长公共子序列(LCS) (O(N2)) 对求得的公共子序列进行去重 (O(N)...
Python编写最长递增子序列
04-18
Python编写最长递增子序列可以使用动态规划的方法来解决。下面是一个示例代码: ```python def longest_increasing_subsequence(nums): n = len(nums) dp = * n # 初始化dp数组,每个元素默认为1 for i in range(1, n): for j in range(i): if nums[i] > nums[j]: dp[i] = max(dp[i], dp[j] + 1) max_length = max(dp) # 最长递增子序列的长度 max_index = dp.index(max_length) # 最长递增子序列的最后一个元素的索引 # 通过回溯找到最长递增子序列 lis = [nums[max_index]] for i in range(max_index - 1, -1, -1): if nums[i] < nums[max_index] and dp[i] == dp[max_index] - 1: lis.insert(0, nums[i]) max_index = i return lis # 测试 nums = [10, 9, 2, 5, 3, 7, 101, 18] result = longest_increasing_subsequence(nums) print(result) ``` 上述代码中,我们使用一个dp数组来记录以每个元素结尾的最长递增子序列的长度。然后通过两层循环遍历数组,如果当前元素大于前面的元素,则更新dp数组中对应位置的值。最后,找到dp数组中的最大值和对应的索引,通过回溯找到最长递增子序列

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
写文章

热门文章

  • 最长递增子序列(LIS) 49177
  • 四种常见背包问题整理 10538
  • WHUT第九周训练整理 5926
  • WHUT第五周训练整理 4307
  • 汉诺塔问题(递归与非递归) 3708

分类专栏

  • 个人题解 32篇
  • 竞赛整理分享 15篇
  • 蓝桥杯 23篇
  • 线段树 10篇

最新评论

  • 1450E Capitalism(差分约束)

    INF_512: 引用「对于不知道方向的边 u − v u-vu−v,满足 ∣ a u − a v ∣ = = 1 |a_u」 根据 a_u - a_v <= 1, a_v - a_u <= 1, 说明有可能 |a_u - a_v| == 0,不满足 |a_u - a_v| == 1了,但执行结果却是对的,有大佬能说说为什么吗?

  • 最长递增子序列(LIS)

    廿七359: 这里求得其实是以1为结尾的递增子序列,没有比1大的数,所以长度是1,你说的2是以3为结尾的递增子序列

  • 最长递增子序列(LIS)

    快乐啦啦啦啦啦: 为啥4 2 3 1 的最长递增子序列长度是1啊,2,3不是递增子序列吗,长度应该是2啊

  • 最长递增子序列(LIS)

    o荷塘月色o: 第一种方法非常棒!很像合唱队问题的解法。另外这题可以转成和排序好的数组寻找LTS,也很方便。

  • 四种常见背包问题整理

    沉默的abbot: 第三个问题,容量是5,只能选第一个的时候,为什么不能选两个体积是2的,价格是6,又没说只能选一个

大家在看

  • 读线圈和离散状态寄存器信息
  • Windows系统分区 二 90
  • [FreeRTOS 功能应用] 互斥访问与回环队列 功能应用
  • SpringBoot+SpringSecurity OAuth2 认证服务搭建实战 (一) 666
  • 青少年编程与数学 01-002数字与编码的世界 05课题、数的关系2_1 570

最新文章

  • 1450E Capitalism(差分约束)
  • 1450F The Struggling Contestant(贪心+思维)
  • 1450C2 Errich-Tac-Toe (Hard Version)(思维)
2020年42篇
2019年38篇
2018年2篇

目录

目录

评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

深圳SEO优化公司坂田模板制作同乐seo网站推广同乐阿里店铺运营坑梓网站建设设计双龙网站搭建沙井网站设计双龙网站推广工具松岗网站制作设计塘坑网页制作南联建网站惠州品牌网站设计荷坳网站建设沙井百搜标王松岗百度网站优化排名石岩seo坪地网站排名优化龙岗外贸网站建设龙岗网站seo优化同乐网站改版宝安百姓网标王推广福永网络推广吉祥百搜词包永湖网站搭建爱联标王大运网站搜索优化盐田阿里店铺托管沙井优秀网站设计平湖SEO按天收费观澜网页制作大芬阿里店铺运营歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

深圳SEO优化公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化