线性dp典中典题目 最长上升子序列(LIS)

本文深入解析最长上升子序列(LIS)问题的两种高效算法:线性动态规划与二分搜索结合单调栈的方法。前者复杂度为O(n^2),通过维护dp数组来更新每个元素作为子序列结尾时的最长序列长度;后者复杂度降低至O(nlogn),利用二分搜索和单调栈优化求解过程,但无法直接获取具体子序列元素。

最长上升子序列(LIS)

首先讲讲什么是子序列:
1.子序列的元素不一定相邻;
2.子序列一定是原序列的子集;

**题目链接**

解法一:
线性动态规划:复杂度(n^2)

我们可以维护一个数组dp[],使得dp[i]为以i元素为结尾的最长上升子序列的长度,那么对于每一个dp[i]而言,初始值都为1;

这种写法对于上面那道题来说,TLE;

代码:

#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define lson k<<1
#define rson k<<1|1
//ios::sync_with_stdio(false);
using namespace std;
const int N=1000100;
const int M=200100;
const LL mod=1e9+7;
int dp[50010];
int a[50010];
int main(){
	ios::sync_with_stdio(false);
	int n;
	cin>>n;
	int mmax=0;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		dp[i]=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);
				mmax=max(dp[i],mmax);
			}
		}
	}
	cout<<mmax<<endl;
	return 0;
}

解法二:

二分搜索+单调栈(也可以说模拟):复杂度为(nlgn)

我的另一篇博客有详细写过

这种写法有个缺陷,就是无法求出最长子序列的具体元素是什么?

不是最后栈里面的元素就是最长子序列,只是长度可以求;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值