Dynamic Programming之Longest Increasing Subsequence (LIS)问题

 Longest Increasing Subsequence(LIS)问题是一类常见的可使用Dynamic Programming解决的算法问题。这个问题是指在一个数字序列中,找到最大个数升序排列的子序列。比如有一个数字序列:

=  { 8 ,   4 ,   1 ,   7 ,   6 ,   2 ,   0 ,   5 ,   3 }


它的LIS就是(1,2,3)和(1,2,5)。除了这个定义以外,还有一种定义叫Longest Increasing Run(不知道怎么翻译),它是指找到相邻的最大个数升序排列的子序列。比如上面的序列中的(1,7)和(0,5)。

        显然找到一个Longest Increasing Run是非常容易的,而找到一个LIS却不怎么简单。

        为了应用Dynamic Programming,我们这里需要建立一个递归来计算最长序列的长度。这里有两种不同时间复杂度的算法:
       

for  i  =   1   to  total - 1
  
for  j  =  i + 1   to  total
    
if  height[j]  >  height[i]  then
      
if  length[i]  +   1   >  length[j]  then
        length[j] 
=  length[i]  +   1
        predecessor[j] 
=  i


        这个算法的时间复杂度为O(n2)。举个例子来演示这个算法,取一个序列如下:

height  =  { 9 ,   5 ,   2 ,   8 ,   7 ,   3 ,   1 ,   6 ,   4 }
length 
=  { 1 ,   1 ,   1 ,   1 ,   1 ,   1 ,   1 ,   1 ,   1 }
predecessor 
=  {nil ,  nil ,  nil ,  nil ,  nil ,  nil ,  nil ,  nil ,  nil}


然后使用这个算法,可以得到如下的结果:

height  =  { 9 ,   5 ,   2 ,   8 ,   7 ,   3 ,   1 ,   6 ,   4 }
length 
=  { 1 ,   1 ,   1 ,   2 ,   2 ,   2 ,   1 ,   3 ,   3 }
predecessor 
=  {nil ,  nil ,  nil ,   2 ,   2 ,   3 ,  nil ,   6 ,   6 }


        另外还有一种O(n log k)的算法,其中k是实际LIS的长度。算法使用一个升序排列的序列A来存储整个LIS。A的初试状态为1个负无穷大和n-1个正无穷大组成的数组。我们要做的就是对整个序列来一次遍历,然后把每个数放到A中去看它是否是属于这个LIS,如果是就把它插入其中。这里所谓是否属于就是指从A的第一个非无穷大的数往前看,如果找到这个一个位置,即前面的数小于这个待插入的数,且后一个数大于那个数。插入的方法就是把后面的那个数替代掉即可。这种查找使用的是Binary Search,它时间复杂度为O(log k)。所以最终整个算法的时间复杂度为O(n log k)。下面给出一个例子:

    0    1    2    3    4    5    6    7    8
a    -
7 , 10 ,   9 ,   2 ,   3 ,   8 ,   8 ,   1

A -i  i
,  i ,  i ,  i ,  i ,  i ,  i ,  i
A -i -
7 ,  i ,  i ,  i ,  i ,  i ,  i ,  i ( 1 )
A -i -
7 , 10 ,  i ,  i ,  i ,  i ,  i ,  i ( 2 )
A -i -
7 ,   9 ,  i ,  i ,  i ,  i ,  i ,  i ( 3 )
A -i -
7 ,   2 ,  i ,  i ,  i ,  i ,  i ,  i ( 4 )
A -i -
7 ,   2 ,   3 ,  i ,  i ,  i ,  i ,  i ( 5 )
A -i -
7 ,   2 ,   3 ,   8 ,  i ,  i ,  i ,  i ( 6 )
A -i -
7 ,   2 ,   3 ,   8 ,  i ,  i ,  i ,  i ( 7 )
A -i -
7 ,   1 ,   3 ,   8 ,  i ,  i ,  i ,  i ( 8 )


参考资料:http://www.comp.nus.edu.sg/~stevenha/programming/prog_dynamicprogramming.html
                    http://www2.toki.or.id/book/AlgDesignManual/BOOK/BOOK2/NODE47.HTM

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值