求数组中最长递增子序列

来源:互联网 发布:大数据新闻的经典案例 编辑:程序博客网 时间:2024/06/05 18:14

《编程之美》第2.16节:求数组中最长递增子序列

问题:写一个时间复杂度尽可能低的程序,求一个一维数组(N个元素)中最长递增子序列的长度。

解法:可以暴力求解,复杂度为O(N^2),另外可以开辟一个数组maxV,其中maxV[i]存放长度为i的递增子序列最大的元素的最小值,用二分法搜索maxV元素,从而使复杂度能够降到O(NlogN)。

代码:

#include<iostream>#include<algorithm>using namespace std;int lowerBinarySearch(int A[],int N,int val){int lo=0,hi=N;while(lo<hi){int mid=(lo+hi)/2;if(A[mid]>=val)hi=mid;elselo=mid+1;}return A[lo]>=val?lo-1:lo;}int longestIncreaseSubarray(int *A,int N){if(N<=1)return N;int *maxV=new int[N+1];maxV[1]=A[0];maxV[0]=INT_MIN;int *lis=new int[N];for(int i=0;i<N;i++)lis[i]=1;int nMaxLis=1;for(int i=1;i<N;i++){int j;j=lowerBinarySearch(maxV,nMaxLis,A[i]);lis[i]=j+1;if(lis[i]>nMaxLis){nMaxLis=lis[i];maxV[lis[i]]=A[i];}else if(maxV[j]<A[i] && A[i]<maxV[j+1])maxV[j+1]=A[i];}return nMaxLis;}int longestIncreaseSubarrayNN(int *A,int N){if(N<=1)return N;int *lis=new int[N];for(int i=0;i<N;i++){lis[i]=1;for(int j=0;j<i;j++){if(A[j]<A[i] && lis[j]+1>lis[i])lis[i]=lis[j]+1;}}int result=0;for(int i=0;i<N;i++)if(lis[i]>result)result=lis[i];return result;}int main(){const int N=10000;int A[N]={};generate(A,A+N,rand);int result=longestIncreaseSubarray(A,N);int resultNN=longestIncreaseSubarrayNN(A,N);cout<<result<<endl;cout<<resultNN<<endl;system("pause");return 0;}
为了验证算法的有效性,这里将暴力算法结果也同时输出了,这样能够对比说明算法的正确性。


0 0