日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

最长单调递增子序列

發布時間:2023/12/4 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 最长单调递增子序列 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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數組的意義??梢允謩幽M一下算法執行的步驟,重要模擬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;

}


轉載于:https://blog.51cto.com/liuyuanxing/1926375

總結

以上是生活随笔為你收集整理的最长单调递增子序列的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。