1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > 最长单调递增子序列(时间复杂度O(nlogn))

最长单调递增子序列(时间复杂度O(nlogn))

时间:2022-03-26 03:44:25

相关推荐

最长单调递增子序列(时间复杂度O(nlogn))

写在前面:仅为个人代码/总结,未必标准,仅供参考!如有错误,还望指出交流,共同进步!

最长单调递增子序列

【题目描述】

找出由n个数组成的序列中的最长单调递增子序列及其长度。

【O(n*n)算法解题思路】

思路一:用数组 b[0:n-1]记录以a[i] (0≤i<n) 为结尾元素的最长递增子序列的长度。序列a的最长递增子序列的长度为max {b[i]} (0≤i<n) 。易知,b[i]满足最优子结构性质,可以递归定义为:b[0]=1, b[i]=max{b[k]}+1(0≤k≤i)。

思路二:将原问题转化为求最长公共子序列问题,求原序列和升序排序后序列的最长公共子序列。

【O(nlogn)算法解题思路】

用归纳解此问题。归纳假设是:已知计算序列a[0:i-1] (i<n)的最长递增子序列的长度的正确算法。从初始情况开始,对于长度为n的序列a[0:n-1],设法转换为求长度小于n的序列的最长递增子序列的长度。

定义P:(0≤i<n) k是序列a[0:i]的最长递增子序列的长度; b[K]是序列a[0:i]中所有长度为k的递增子序列中的最小结尾元素值。若w等于某一个b[k]的值,则pre[w]用于存储排在w前面的所有长度为k-1的递增子序列中的最小结尾元素值。

具体解题步骤如下:

在由i-1到i的循环中,

①当a[i]>b[k]时,k=k+1, b[k]=a[i],否则k值不变。

②当a[i]≤b[k]时,如果a[i]<b[1].则将b[1]的值改变为a[i]。当b[1]≤a[i]≤b[k]时,用二分搜索算法找到有序的数组b下标j,使得b[i-1]≤a[i]<b[j]。b[j-1]<a[i]<b[j]时, b[1:j-1]和b[j+1:k]的值不变, b[j]的值改变为a[i]。b[j-1]==a[i]时,保持不变。

③对于记录最长递增子序列,可在求得每一个b[j]时用pre[b[i]]记录b[j]的前驱数据为b[j-1],即排在b[j]前面的序列a[0:i-1]的所有长度为j-1的递增子序列中的最小结尾元素值。

【解题过程遇到的问题】

问:为什么步骤的第②点中当b[j-1]==a[i]时要保持不变?

答:来个例子,比如序列1 2 3 2,当i递增到3时,发现a[i]==b[2],但如果将b[3]改为a[i],这会得到2是长度为3的递增子序列中的最小结尾元素值,这虽然不影响求得原序列的最长单调递增子序列长度为3,但如果要根据数组b来记录最长单调递增子序列则行不通,因为将b[3]改为2后已不满足b[k]的定义,2并不是a[0…3]中长度为3的单调递增子序列的最小结尾值,2,2不构成递增关系。

【样例解答】

【实现代码】

#include <bits/stdc++.h>using namespace std;int a[101]={0};int b[101]={0};int pre[101]={0};int n;stack <int> S;//k是序列a[0:i]的最长递增子序列的长度//b[k]是序列a[0:i]中所有长度为k的递增子序列中的最小结尾元素值//假若w等于某一个b[k],则pre[w]存排在w前面的所有长度为k-1的递增子序列中的最小结尾元素值int binary(int i,int k){int u=k;if(a[i]<b[1]){return 1;}//二分法查找满足b[j-1]<=a[i]<b[j]的jfor(int h=1,j=k;h!=j-1;){if(b[k=(h+j)/2]<=a[i])h=k;elsej=k;u=j;}return u;}int LIS(){int v;b[1]=a[0];for(int i=1,k=1;i<n;i++){if(a[i]>b[k])//a[i]>b[k]{b[++k]=a[i];pre[a[i]]=b[k-1];}else//a[i]≤b[k]{int m=binary(i,k);if(a[i]!=b[m-1]){pre[a[i]]=b[m-1];b[m]=a[i];}}v=k;}return v;}int main(){cin>>n;for(int i=0;i<n;i++){cin>>a[i];}int res=LIS();cout<<res<<endl;int index=b[res];S.push(index);while(pre[index]!=0){S.push(pre[index]);index=pre[index];}while(!S.empty()){cout<<S.top()<<' ';S.pop();}return 0;}/*157 2 5 6 3 4 9 8 12 13 26 14 30 20 21*//*72 4 3 5 6 4 8*//*812 13 14 1 2 3 2 4*/

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。