编程之美--数组中的最长递增子序列(LIS longest increasement sequence)

最早见到这道题目是在poj中,具体的题目忘记了,但是所要求的算法是一致的。

 

当时在学习LCS,因此想了一种和LCS比较相似的解法:

 

对原数组使用快速排序,然后使用LCS的思想求最大公共字串。 这种解法比较容易理解,但是所需要的空间为:O(2N) = O(N);时间为O(N^2+N*lgN) = O(N^2),显然这不是一种最优的解法。但是当时还真没有想到更好的解法……

 

最近看到编程之美上面的题目,然后豁然开朗。

 

书中提供了两个解法:

 

1. 根据无后效性的定义,可以使用DP来进行求解。根据递推公式:LIS[i+1] = max{LIS[i+1],LIS[k]+1} (当Data[i+1] > Data[k], 并且k∈[0,i]

在得出了上述的通项公式之后,可以简单的写代码求解了。但是这里需要注意的就是在for循环当中不停地更新当前的最大值,方便函数最后的结果返回。这个解法是传统的DP,因此时间复杂度为O(N^2),空间复杂度为O(N),但是在渐进意义上优于我的解法。

 

2. 当考虑前i个元素对i+1个元素的影响时,可以这样简答的理解:当子序列的最大元素比当前元素小时,就可以把当前元素添加到这个序列后面,构成一个新的LIS。

因此需要找到前i个元素的一个LIS,而且这个LIS的最大元素比Array[i+1]小,且长度尽可能的长。

为了加速算法的实现,构建一个长度为N的数组来维护长度为i的LIS的最大值。

因此该算法的时间复杂度是O(N^2),空间复杂度是O(2N) = O(N)。

 

上述算法的实现如下:

(二分查找的改进没有实现……)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值