这题目是经典的DP题目,也可叫作LIS(Longest Increasing Subsequence)最长上升子序列 或者 最长不下降子序列。很基础的题目,有两种算法,复杂度分别为O(n*logn)和O(n^2) 。


利用LCS算法实现
思路:设原序列为A[],将A[]进行排序后生成排好序的序列B[],利用LCS 算法查找A[],B[]的最长公共子序列即可找出LIC。
时间复杂度:分为排序和LCS两块,最终为O(n^2)
代码可以参考前面的关于LCS的文章。


动态规划的思想

定义L(j)={ max(L(i))+1, i 代码实现:

#include  #define SIZE 10000 #include  #include  using namespace std; //a[]为序列数组,d[t]记录0...t的LIS的最大长度,p[]记录前一个LIS的位置 void LIS(int *a,int length,int *d,int* p) {     int i,j;     d[0]=1;p[0]=-1;             //初始化,以a[0]结尾的最长递增子序列长度为1     for(i=1;ia[j]&&d[j]+1>d[i])             {                 d[i]=d[j]+1;                 p[i]=j;            //记录位置             }     } } void printAnswer(int *d,int* p,int length) {     int i,j,max=0;     for(i=0;imax)         {             max=d[i];             j=i;         }     }     cout<<"Max length:"< vec;     for(i=0;i::iterator iter = vec.begin() + index;     	a[i]=*iter;         vec.erase(iter);     }     cout<<"LIS:"< 
  
运算结果:



O(nlgn)算法

目的:在前i个元素中的所有长度为len的递增子序列中找到这样一个序列,它的最大元素比arr[i+1]小,而且长度要尽量的长,如此,我们只需记录len长度的递增子序列中最大元素的最小值就能使得将来的递增子序列尽量地长。

方法:维护一个数组MaxV[i],记录长度为i的递增子序列中最大元素的最小值,并对于数组中的每个元素考察其是哪个子序列的最大元素,二分更新MaxV数组,最终i的值便是最长递增子序列的长度。

代码实现:

//在a[0]..a[len]中,找到最大的j,满足a[j] <= n int find(int *a,int len,int n) {     if(len==1) return 1;     int left=0,right=len-1,mid=(left+right)/2;     while(left<=right)     {         if(n>a[mid]) left=mid+1;         else if(nc[len]) j=++len;         else j=find(c,len,a[i]);         c[j]=a[i];     }     cout<<"MaxLength"< 
  
int main() {     int i,a[SIZE],d[SIZE],p[SIZE],c[SIZE];     vector vec;     for(i=0;i	vector::iterator iter = vec.begin() + index;     	a[i]=*iter;         vec.erase(iter);     }     cout<<"LIS:"< 
  
得到的结果与前面的算法相同,不过只能打印出LIS的大小,还没想到怎样去打印出序列。