最长递增子序列

最长递增之序列简称:LIS是一道很经典的算法题,问题定义如下

给定一个无序的数组,找出长度最长的单调递增的子序列(不一定要相邻) 

解法可以采用动态规划,有两种方法:

1.将源数组a 排序得到另一个数组b,然后在这两个数组中求LCS即(最长公共子序列)复杂度为 nlogn + n2 

2.将源数组a直接采用动态规划,递推式很简单,如果第k位加入数组中,那么以k结尾的子序列的长度可以由(0。k-1)递推出来,即:

f(k) = max( f(j)) +1  if a[k] > a[j]  其中j<k

扩展下 如果要把LIS的序列找出来 。可以用一个N*N的数组将路径记录下来。每替换一次更新即可:
代码如下:

int LIS(int a[],int l)
{
     
int *buffer = new int[l];
     
int *index = new int[l];
     
int **path = new int*[l];
     
for(int k = 0;k<l;k++)
     {
        path[k] 
= new int[l];
        memset(path[k],
0,sizeof(int)*l);
     }
     
for(int i = 0;i<l;i++)
     {
         
int select= -1;
         buffer[i] 
= 1;
         path[i][i] 
= 1;
         
for(int j = 0;j<i;j++)
         {
             
if(a[i]>a[j]&& buffer[i]>=buffer[j] -1)
             {
                 buffer[i] 
= buffer[j] +1;
                 select 
= j;
             }
         }
         
if(select!= -1)
         {
            
for(int h = 0;h<i;h++)
                path[i][h] 
= path[select][h] ;
         }
     }
     
int max_path = 0;
     
int m = buffer[0];
     
for(int j =1;j<l ;j++)
         
if(buffer[j]>m)
         {
             m 
= buffer[j];
             max_path 
= j;
         }
     
for(int g= 0;g<l;g++)
     {
         
if(path[max_path][g])
             cout
<<a[g]<<" ";
     }
     cout
<<endl;
     delete [] buffer;
     buffer 
= NULL;
     delete [] index;
     index 
= NULL;
     
for(  k = 0;k<l;k++)
     {
         delete [] path[k];
         path[k] 
= NULL;
     }
     delete [] path;
     path 
= NULL;
     
return m;
}
void main()
{


    
int t[]={1,5,3,4,4,5,7,4,2,5,7,8,6,4,3,3,4,5,6,7,7,7,65,34,3,3};
    cout
<<LIS(t,sizeof(t)/sizeof(int));
}

 

 

posted @ 2010-08-15 20:43  David Luo  阅读(337)  评论(0编辑  收藏  举报