最長單調遞增子序列


1.問題描述:

求一個正整數序列的最長單調自增子序列,子序列不要求是連續的。例如

Input:5

5 2 4 3 1

Output:2

2. 算法復雜度是O(N*N)

f[i]是以a[i]為最大值的子序列,那么f[]的最大值就是要的結果。

int f[],a[];

f[0] = 1;

for(i = 1 ; i < n ; i++ )

{

  f[i] = 1;

  for(j = 0 ; j < i ; j++)

  {

    If(a[j] < a[i] && f[j]+1 > f[i])//等號有沒有要視題目而定

    {

      f[i] = f[j] +1;

    }

  }

}

很顯然實踐復雜度是O(N*N),那么有沒有更快的算法呢?按照正常的思路更快的復雜度應該就是O(N*logN),那么就要涉及到二分了。

 

3. 算法復雜度是O(N*logN)

可是話又說回來,那個logN到底怎么實現的呢?上網搜了搜說的都有點抽象,捉摸了一下,是這個樣子滴!建立一個輔助數組c[n],c[i]存儲的是子序列長度為i的序列最后一個值(實際上子序列長度為i的子序列有多個,要的是子序列最后一個值最小的。后面解釋后什么!!!)。這時要遍歷要處理的數組a[n],for(i=1;i<n;i++)//從第二值開始,因為第一個值用來初始化了

{

  j=find(c,n+1,a[i]);//find是一個二分查找

  c[j]=a[i];

  b[i]=j;

}

請看一下上面的例子實際執行的情況:C數組變化的情況

-1 5

-1 2

-1 2 4

-1 1 2

-1 1 4

-1 1 3

A數組遍歷是從前往后的,處理a[i-1]a[i]以及后面的值肯定還沒有處理,前面的值都處理過了,看c數組,每個a數組中的值和c數組中值進行比較,找到合適的位置插入(若插入到c數組的末尾,那么就屬於最長遞增子序列長度加1,實際上c數組的長度就是最后的最長單調遞增子序列的長度。),否則這就替換掉了c數組中原來位置存儲的值,這種替換時有意義的,主要是為了后來的a數組中的值計算b用(b[i]中保存的是以a[i]為最后一個元素的最長單調遞增子序列。)好處是若a[i] <a[j],b[i]=b[j],那么在c中肯定要保存a[i]呀!!(注意c數組的下標代表的是子序列的長度,c數組中的值也是按遞增順序排列的。這才可能用二分呢,親)。和O(N*N)的主要區別就是巧妙的借用了c數組,本題的關鍵就是理解c數組的意義。可以手動模擬一下算法執行的步驟,重要模擬cb數組的變化情況。下面給出完整的算法。

 

#include <iostream>

using namespace std;

 

int find(int *a,int len,int n)//二分find

{

  int left=0,right=len,mid=(left+right)/2;

  while(left<=right)

  {

    if(n>a[mid]) left=mid+1;

    else if(n<a[mid]) right=mid-1;

    else return mid;

    mid=(left+right)/2;

  }

  return left;

}

void fill(int *a,int n)

{

  for(int i=0;i<=n;i++)

    a[i]=1000;//這就是一個初始化,無所謂!!

}

int main()

{

  int max,i,j,n,a[100],b[100],c[100];

  while(cin>>n)

  {

    fill(c,n+1);

    for(i=0;i<n;i++)

      cin>>a[i];

    c[0]=-1;//要懂得用這種天然的最小值

    c[1]=a[0];//初始化

    b[0]=1;//b[i]表示以a[i]結尾的最長單調遞增子序列

    for(i=1;i<n;i++)//復雜度是N

    {

      j=find(c,n+1,a[i]);//復雜度是logN

      c[j]=a[i];

      b[i]=j;

    }

     for(max=i=0;i<n;i++)//遍歷一遍找到最大值

      if(b[i]>max)

        max=b[i];

    cout<<max<<endl;

  }

  return 0;

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM