编程之美2.16——求数组中最长递增子序列

如:1,-1,2,-3,4,-5,6,-7中,最长递增子序列是1,2,4,6.

【解法1】

假设在目标数组array[]的前i个元素中,最长递增子序列的长度为LIS[I],

那么对于任意k<=i,当array[i+1]>array[k]时,LIS[i+1]=LIS[K]+1,否则LIS[i+1]=1。

此法特点:在考虑第i+1个元素的时候不考虑前面i个元素的情况。

代码:

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】

对于前面i个元素的任何一个递增子序列,如果这个子序列的最大元素比array[i+1]小,那么就可以将array[i+1]加在这个子序列后面,构成一个新的递增子序列。

因此,要找到前i个元素中的一个递增子序列,使得这个递增子序列的最大的元素比array[i+1]小,且长度尽量长。这样便可找到以array[i+1]为最大元素的最长递增子序列。

假设:

在数组前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;
}
原文地址:https://www.cnblogs.com/ketchups-notes/p/4552203.html