(LIS)最长上升序列(DP+二分优化)

求一个数列的最长上升序列

  动态规划法:O(n^2)

 1 //DP
 2 int LIS(int a[], int n)
 3 {
 4     int DP[n];
 5     int Cnt=-1;
 6     memset(DP, 0, sizeof(DP));
 7     for(int i=0; i<n; i++ )
 8     {
 9         for(int j=0; j<i; j++ )
10         {
11             if( a[i]>a[j] )
12             {
13                 DP[i] = max(DP[i], DP[j]+1);
14                 Cnt = max(DP[i], Cnt);//记录最长序列所含元素的个数
15             }
16         }
17     }
18     return Cnt+1;//因为初始化为0,所以返回结果+1
19 }

贪心+二分法:O(nlogn) 

分析:要让一个序列具有最长上升子序列,其实就是保证子序列中的每个元素尽可能小,降低门槛,让后面的元素尽可能多进入该子序列

实现:定义一个最长子序列数组Array,以及当前长度Len,从头到尾维护数组a

a. a[i]>Array[i] (当前元素大于子序列结尾元素),则a[i]进入子序列:Array[++len] = a[i]

b. a[i]<=Array[i],这时对Array进行维护,把Array中比a[i]大的第一个元素替换成a[i](这样可以降低后面元素进入子序列的门槛。

c. 为了降低算法复杂度,因为Array是升序序列,所以用lower_bound查找Array中第一个大于等于a[i]的元素

 1 //贪心+二分
 2 int LIS(int a[])
 3 {
 4     int Cnt=0;
 5     int Array[n+1];
 6     Array[0] = a[0];
 7     for(int i=1; i<n; i++ )
 8     {
 9         if( a[i]>Array[Cnt] )
10             Array[++Cnt]=a[i];
11             else
12             {
13                 int Index=lower_bound(Array, Array+Cnt+1, a[i])-Array;
14                 Array[Index]=a[i];
15             }
16     }
17     return Cnt+1;
18 }

求最长下降子序列:

    不需要再写LDS---直接将要求的数组倒序,倒序数组的最长上升子序列长度=原数组最长下降子序列长度。

原文地址:https://www.cnblogs.com/wsy107316/p/11502538.html