最长单调递减子序列

来源:互联网 发布:网络教育统考成绩时间 编辑:程序博客网 时间:2024/05/17 23:20

方法一:普通动态规划算法,时间复杂度O(n2)。

int LIS(int a[], int n){int i, j, k;int maxlen;int *b=new int[n];for(i=0, b[0]=1; i<n; i++){for(j=0, k=0; j<i; j++){if(a[j]>a[i] && k<b[j])k=b[j];b[i]=k+1;}}maxlen=0;for(i=0; i<n; i++)if(b[i]>maxlen)maxlen=b[i];return maxlen;}int main(){int a[]={9,4,3,2,5,4,3,2};cout<<LIS(a, 8)<<endl;}

 

方法二:采用二分搜索算法,时间复杂度O(nlgn)。

 0<=i<n,k是序列a[0:i]的最长单调递减子序列的长度。b[k]是序列a[0:i]中所有长度为k的递减子序列中的最大结尾元素值。

在由i-1到i的循环中,如果a[i]<b[k],则k++,b[k]=a[i];否则k值不变,但要更新b数组。怎么更新b数组呢?如果a[i]>b[1],则b[1]=a[i];若a[i]<b[1],注意到数组b是递减的,则二分搜索找到b[j-1]>a[i]>b[j],更新b[j]=a[i]。

 

int LIS(int a[], int n){int i=0, k;int l, h;int *b=new int[n+1];b[1]=a[0];for(i=1, k=1; i<n; i++){if(a[i]<b[k]) b[++k]=a[i];else{//更新b[]if(a[i]>b[1]) b[1]=a[i];else{//二分查找for(l=1, h=k; l!=h-1; ){int mid=(l+h)/2;if(b[mid]<=a[i]) h=mid;elsel=mid;}b[h]=a[i];}}}return k;}int main(){int a[]={9,4,3,2,5,4,3,2};cout<<LIS(a, 8)<<endl;}