数组最长递增子序列

来源:互联网 发布:翻页相册制作软件 编辑:程序博客网 时间:2024/05/01 21:12

求一维数组中的最长递增子序列,也就是着一个标号的序列 b[0],b[1],…,b[m] ( 0 <= b[0] < b[1] < … < b[m] < N ),使得 array[b[0]] < arrary[b[1]] < … < array[b[m]].

Sample思路
分析目标串:1,-1,2,-3,4,-5,6,-7。
使用i来表示当前遍历的位置:
当i=1,显然最长的递增序列为(1),序列长度为1。
当i=2,由于-1<1。因此需要丢弃第一个值重新建立串(-1),当前长度仍为1。
当i=3,由于2>1,2>-1。因此,最长序列为(1,2),(-1,2),长度为2。
依次类推之后,
假设在目标数组array[]的前i个元素中,最长递增子序列的长度为LIS[i]。那么,
LIS[i+1] = max{1,LIS[k]+1},array[i+1]>array[k],for any k<=i
即如果array[i+1]大于array[k],那么第i+1个元素可以接在LIS[k]长的子序列后面构成一个更长的子序列。

Optimize思路
前面的分析是,当考察第i+1个元素的时候,我们不考虑前面i个元素的分布情况。现在我们从另一个角度分析,在考察第i+1个元素的时候同时考虑前面i个元素的情况。
对于前面i个元素的任何一个递增子序列,如果这个子序列的最大元素比array[i+1]小,那么就可以将array[i+1]加在这个子序列后面,构成一个新的递增子序列。
比如当i=4的时候,目标序列为1,-1,2,-3,4,-5,6,-7最长递增子序列有(1,2),(-1,2)。那么只要4>2,就可以把4直接增加到前面的子序列。
因此,我们需要找到前i个元素中的一个递增子序列,使得这个递增子序列的最大元素比array[i+1]小,且长度尽量地长。
仍然假设在数组的前i个元素中,以array[i]为最大元素的最长递增子序列的长度为LIS[i]。
同时,假设:
长度为1的递增子序列最大元素的值为MaxV[1];
长度为2的递增子序列最大元素的值为MaxV[2];
……
长度为LIS[i]的递增子序列最大元素的值为MaxV[LIS[i]]。

#include <stdio.h>const int INF=100000000;int Max(int a,int b){    return a>b?a:b;}// O(N^2+N) = O(N^2)int LIS_Sample(int* array,int n){    int *LIS = new int[n];  //前i个元素中,最长递增子序列的长度为LIS[i]    int Max_LIS = 1;    for(int i=0;i<n;i++){        LIS[i] = 1;        for(int j=0;j<i;j++){   //前面最长的序列            if(array[i] > array[j])                LIS[i] = Max(LIS[i],LIS[j]+1);        }        Max_LIS = Max(Max_LIS,LIS[i]);    }    delete LIS;    return Max_LIS;}int LIS_Optimize(int* array,int n){    int *MaxV = new int[n+1];   //保存长度为i的递增子序列最大元素的值    int *LIS = new int[n];      //以array[i]为最大元素的最长递增子序列的长度为LIS[i]    int Max_LIS = 1;            //数组最长递增子序列的长度      MaxV[0] = -INF;    MaxV[1] = array[0];    //初始化最长递增序列的信息;    for(int i=0;i<n;i++)         LIS[i] = 1;    for(int i=1;i<n;i++){        //遍历历史最长递增序列信息        int j=0;        for(int j = Max_LIS; j>=0;j--){            if(array[i] > MaxV[j]){                LIS[i] = j+1;                break;            }        }        //如果当前最长序列大于最长递增序列长度,更新最长信息        if(LIS[i] > Max_LIS){            Max_LIS = LIS[i];            MaxV[LIS[i]] = array[i];        }        else if(MaxV[j]<array[i] && array[i] < MaxV[j+1]){            MaxV[j+1] = array[i];        }    }    /*    //打印序列    stack<int> s;    s.push(array[max_index]);    int len = 1;    int last = array[max_index];    for(int i=max_index-1;i>=0;i--){        if(LIS[i] == (Max_LIS-len) && array[i] < last)            s.push(array[i]),len++;    }    while(!s.empty()){        printf("%d ",s.top());        s.pop();    }    printf("\n");    */    return Max_LIS;}int main(){    int a[8] = {1,-1,2,-3,4,5,6,-7};    printf("Sample calculate the longest length is %d\n",LIS_Sample(a,8));    printf("Optimize calculate the longest length is %d\n",LIS_Optimize(a,8));    return 0;}
0 0
原创粉丝点击