最長上升子序列


1. 思路

最近在網上看到一個很好的解法,時間復雜度為O(nlogn),空間復雜度為O(n)。

我們假設存在一個序列a=[3,2,1,4,7,5,6],並且將數組b存儲最長上升子序列的最后一個數字的最小值,例如b[1]存儲長度為1的上升子序列的最后一個數字的最小值,以此類推。

除此之外,我們假設最長上升子序列的長度初始值為t=1,並且初始值b[0]=minInt,b[1]=maxInt。

從第一個數開始,不斷計算

i=1,x=3, 當前最長上升子序列的長度為1,最后一位數字的最小值為maxInt, 首先3<maxInt, 所以3 不能作為最長子序列2 的最后一個數字,並且他可以作為最長子序列1的最后一個數字,因此更新b[1]=3;

i=2,x=2, 同樣不能增加最長子序列的長度,只能更新b[1]=2;

i=3,x=1, b[1]=1;

i=4,x=4, 其中4>b[t],因此t++ 最長上升子序列的長度可以增加,再t++之后b[t]=4;

i=5,x=7, 其中7>b[t],因此t++,此時t=3, b[3]=7;

i=6,x=5, 查找b數列,發現b[2]<5,b[3]>5, 因此更新b[3]=5;

i=7,x=6,查找b數列,發現b[3]<6, 因此t++,t=4,b[4]=6;

因此最長上升子序列長度為t,t=4;

對於查找b數列,使用二分法,達到O(logn)的效果。

2. 示例

2.1 題目

點擊打開鏈接 poj的題目

2.2 代碼

#include<stdio.h>
int search(int b[], int length,int x){
    int l=1,r=length;
    while(l<r){
        int mid = (l+r)/2;
        if(b[mid]>x) r=mid;
        if(b[mid]<x) l=mid+1;
        if(b[mid]==x) return mid;
    }
    return l;
}
int b[100100];
int  main()
{
     int i,j,n,x,t;
     while(scanf("%d",&n)==1){
         t=1;
         b[0]=-999999;
         b[1]=99999999;
         for(i=0;i<n;i++){
            scanf("%d",&x);
            if(b[t]<x)
                b[++t]=x;
            else
                b[search(b,t,x)]=x;
         }
         printf("%d\n",t);
     }
     return 0;
}



注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



最長上升子序列 最長上升子序列 最長上升子序列 最長上升子序列 最長上升子序列 最長上升子序列 最長上升子序列 最長上升子序列 最長上升子序列 最長上升子序列
 
粤ICP备14056181号  © 2014-2020 ITdaan.com