最长上升子序列(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)
这种写法有个缺陷,就是无法求出最长子序列的具体元素是什么?
不是最后栈里面的元素就是最长子序列,只是长度可以求;
本文深入解析最长上升子序列(LIS)问题的两种高效算法:线性动态规划与二分搜索结合单调栈的方法。前者复杂度为O(n^2),通过维护dp数组来更新每个元素作为子序列结尾时的最长序列长度;后者复杂度降低至O(nlogn),利用二分搜索和单调栈优化求解过程,但无法直接获取具体子序列元素。
19万+

被折叠的 条评论
为什么被折叠?



