当前位置:   article > 正文

LIS-最长上升子序列

LIS-最长上升子序列

LIS(最长上升子序列)是一个经典的问题。

首先我们来介绍子序列的概念:

子序列指的是一个序列中,按照原顺序选出若干个不一定连续的元素所组成的序列。

LIS有两种算法模型:一种是复杂度为O(n^{^{2}})的dp模型,另外一种是复杂度为O(nlogn),利用二分实现的模型。

模型一:复杂度为O(n^{^{2}})的dp模型

我们首先定义状态:
我们定义dp[i]为以a[i]结尾的最长上升子序列长度。
设置 j为小于 i 的某一点,那么当 a[j] < a[i] 时,必然有,以 a[j]结尾的最长上升子序列,现在能以 a[i]结尾,并且长度+1
因为j < ia[j]< a[i],满足上升子序列的要求。
所以 dp[i]的一条转移路径为 dp[i]=dp[j]+1
但是  j是比i小的某一个值,所以转移到 dp[i]这一状态的值很多,我们要选择最优状态。所以 dp[i]的状态转移:
dp[i]=max(dp[j]+1,dp[i]);
那么当 a[j] > a[i]
此时肯定不满足上升子序列,所以 dp[i]dp[j]毫无关联。
由此我们可以写出 LIS 的算法:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. using ll = long long;
  4. const int N=1e3+10;
  5. int n;
  6. ll a[N],dp[N];
  7. int main()
  8. {
  9. cin>>n;
  10. for(int i = 1;i <= n;i++) {
  11. cin >> a[i];
  12. dp[i]=1;
  13. }
  14. for(int i = 1;i <= n;i++)
  15. {
  16. for(int j = 1;j < i;j++)
  17. {
  18. if(a[i] > a[j]) dp[i]=max(dp[i],dp[j]+1);
  19. }
  20. }
  21. ll ans = 0;
  22. for(int i = 1; i <= n; i++){
  23. ans = max(ans,dp[i]);
  24. }
  25. cout<<ans<<endl;
  26. return 0;
  27. }

模型二:复杂度为O(nlogn),利用二分实现的模型。

当数据量较大,使用常规的O(n^2)的LIS算法会超时
故采用二分+贪心的算法求解: 
维护一个low数组,low[i]表示长度为 i 的最长上升子序列的末尾元素
使用贪心思想来对low数组进行更新,核心思想是末尾元素越小,越容易凑出最长的子序列
遍历每一个元素,若当前元素比low[i]更大,则直接加入low数组的末尾 
若当前元素小于low[i],则从low数组中找到一个大于等于它的最小值将其替换
由于low数组是递增的,故使用二分算法进行搜索和替换
最终输出low数组的长度即为答案 。

注意此算法的缺陷:low数组只有长度是有意义的,其保存的元素是无意义的。

由此我们可以写出 LIS 的算法:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. using ll = long long;
  4. const int N = 3e5 + 10;
  5. ll a[N],low[N];
  6. int main(){
  7. int n,length = 1;
  8. cin >> n;
  9. for(int i = 1; i <= n; i++){
  10. cin >> a[i];
  11. }
  12. low[1] = a[1]; //初始化,长度为1的子序列初始化为第一个元素
  13. for(int i = 2; i <= n; i++){
  14. if(a[i] > low[length]){ //若当前元素大于low数组末尾元素,直接插入
  15. low[++length] = a[i];
  16. }else{ //若小于,则用low数组中刚好大于等于它的元素替换之
  17. int index = lower_bound(low + 1, low + length + 1,a[i]) - low; //获取插入位置下标
  18. low[index] = a[i]; //替换
  19. }
  20. }
  21. cout << length <<endl; //输出low数组长度即为答案
  22. return 0;
  23. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/315553
推荐阅读
相关标签
  

闽ICP备14008679号