編程之美2.16——求數組中最長遞增子序列

如:1,-1,2,-3,4,-5,6,-7中,最長遞增子序列是1,2,4,6.數組

【解法1】spa

假設在目標數組array[]的前i個元素中,最長遞增子序列的長度爲LIS[I],code

那麼對於任意k<=i,當array[i+1]>array[k]時,LIS[i+1]=LIS[K]+1,不然LIS[i+1]=1。blog

此法特色:在考慮第i+1個元素的時候不考慮前面i個元素的狀況。class

代碼:di

int longestSub(int a[], int n)
{
    int *LIS=new int[n];
    int max=0;
    for(int i=0; i<n; i++){
        LIS[i]=1;
        for(int j=0; j<i; j++)
            if(a[i]>a[j]&&LIS[j]+1>LIS[i])
                LIS[i]=LIS[j]+1;
        if(max<LIS[i])
            max=LIS[i];
    }
    delete [] LIS;
    return max;
}

【解法2】co

對於前面i個元素的任何一個遞增子序列,若是這個子序列的最大元素比array[i+1]小,那麼就能夠將array[i+1]加在這個子序列後面,構成一個新的遞增子序列。let

所以,要找到前i個元素中的一個遞增子序列,使得這個遞增子序列的最大的元素比array[i+1]小,且長度儘可能長。這樣即可找到以array[i+1]爲最大元素的最長遞增子序列。new

假設:return

在數組前i個元素中,以array[i]爲最大元素的最長遞增子序列的長度爲LIS[i]。

長度爲i的遞增子序列最大元素的最小值爲maxV[i]。。。

代碼:

int LIS(int a[], int n)
{
    int *maxV=new int[n+1];
    int *LIS=new int[n];
    int amin=a[0];
    for(int i=0; i<n; i++)
        if (amin>a[i])
            amin=a[i];
    maxV[1]=a[0];
    maxV[0]=amin-1;//邊界值
    for(int i=0; i<n; i++)
        LIS[i]=1;
    int nMaxLIS=1;//最長子序列長度
    for(int i=1; i<n; i++)
    {
        int j;
        for(j=nMaxLIS; j>=0; j--)
        //for(j=LIS[i-1]; j>-1; j--)
        {
            if(a[i]>maxV[j])
            {
                LIS[i]=j+1;
                break;
            }
        }
        if(LIS[i]>nMaxLIS){
            nMaxLIS=LIS[i];
            maxV[LIS[i]]=a[i];
        }
        else if(maxV[j]<a[i]&& a[i]<maxV[j+1]){
            maxV[j+1]=a[i];//更新最大元素最小值
        }
    }
    return nMaxLIS;
}
相關文章
相關標籤/搜索