您的位置:首页 > 其它

最长递增子序列问题

2011-09-18 21:26 183 查看
设有n个数,求这个数组中最长的递增子序列。 子序列不必在原数组中是连续的。

即有:A0,A1,A2 ... An-1,求出序列: Aj1,Aj2,...Aik  该序列递增,并且其中: j1 < j2 < .. <jk, 求出最大的k。

例如对于数组: 2,3,11,6,8,4,7,12,1,9

最长递增子序列是: 2 3 4 6 8 12

求解方法如下:

设F(i)表示以A[i]结尾的最长递增子序列的长度,这里F(n)不是我们要求解的最终答案。但是如果所有的F(i),  0 <= i  < n 都求出来,该数组中最大的即是我们所求。

F(i) 与 F(i-1)有什么关系吗?

很容易得到: 由于F[i]表示以A[i]结尾的所有序列中最大的一个,如果A[i] > A[j], 说明A[i]可以追加到序列F[j]之后,否则不能追加,F[i] 是A[i]能够追加的所有这些子序列中最大的一个。递推关系如下:

F(i) = max (F(j) + 1, 如果A[i] > A[j], 并且F(i) < F(j)  )  0 <= j < i 。

如要输出求到的序列,需要保存每个以A[i]结尾构成的序列,代码如下:

#include<stdio.h>

#define MAX (256)

int main()

{    

     int i,j,n,k;

     int mpos = 0;

     int mval = 0;

     int f[MAX];

     int a[] = {2,3,11,6,8,4,7,12,1,9};

     n = 10;

     

     int res[MAX][MAX] = {0};

     

     for(i=0;i<n;i++) {

        f[i]=1;

        res[i][i] = a[i];

     }

                                                                         

    for(i=1;i<n;i++){

        for(j=0;j<i;j++){

           if(a[j]<a[i] && f[j]+1 > f[i]) {

                  f[i]= f[j]+1;   

                 // i的序列在j之上

                  for(k = 0; k <= j; ++k) 

                      res[i][k] = res[j][k];       

           }

         }        

     }

     mval = f[0];        

     for(i = 1; i < n; ++i) {

            if(f[i] > mval ) {

               mval = f[i];

               mpos = i;

            }

     }

  printf("max value = %d, pos = %d\n",mval,mpos);

  for(i = 0; i < n; ++i) {

        if(res[mpos][i] != 0)

           printf(" %d ",res[mpos][i]);      

  }  

  printf("\n");

      

return 0;



    
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ini