LIS问题(最长递增子序列)

最长递增子序列


简介:

今天的算法课上学习了动态规划(Dynamic programming),简单的来说,动态规划解决问题就是在解决问题的过程中通过不断的解决一些小问题最终解决大问题,并且与分治算法的区别是它并不要求小问题要比大问题规模小很多,其中LIS问题是我们主要学习的例子:

LIS问题

给定一个数的序列a1,a2...an
找到最长的递增子序列

解法:

  1. 动态规划O(n*n):
    动态规划方程:
    L(j) = 1+max{L(i):i < j}
    具体过程:
    L[n]是一个存储序列长度的数组,初始化为1;
    对于序列中的每一个值来说,遍历坐标小于它的值,观察其序列长度+1是否大于他本身的序列长度。 这样我们就可以得到每一个值得序列长度,最后找到数组L中的最大值即可,很容易看出其复杂度为O(n*n);
    如果我们想要得到最长子序列,只需添加prev[j]存储前驱结点即可。
  2. 改进O(n*logn)
    我们考虑:在动态规划中的内部循环,我们采用遍历的方式查询,是否可以采用其他方式使其复杂度降低?
    在计算每一个L(j)时,都要找出最大的L(i) (i < j);
    我们采用一个B序列,来记录最大递增子序列的最末元素,B[L(j)] = aj;
    对于B采用二分查找,找到使得B中小于目标值的最大值的下一个为目标。
    举个例子:a[1-6] = {2, 1, 5, 8 , 9 , 7}
    初始化B[6], len = 1, B[1] = 2;
    a[2] < B[1] B[1] = 1 len = 1;
    a[3] > B[1] B[2] = 5 len = 2;
    a[4] > B[2] B[3] = 8 len = 3;
    a[5] > B[3] B[4] = 9 len = 4;
    a[6] < B[3]&a[6] > B[2] B[3] = 7 len = 4;
    len即为最长子序列的长度,而1,5,7, 9 并不是一个子序列,只不过是对应长度子序列的最末元素的最小值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值