图解算法:LIS问题,单调队列+二分优化

关注下方公众号,分享硬核知识

作者 | 小K

出品 | 公众号:小K算法 (ID:xiaok365)

01

故事起源

LIS:Longest Increasing Subsequence(最长递增子序列)。
给你一个整数数组,如何求出其中最长的严格递增子序列的长度?

比如下面绿色和蓝色都是符合要求的子序列,但蓝色的子序列更长,所以最大长度为4。

02

思考

要求最长子序列的长度,那肯定要先找出这个最长的子序列。比如下面蓝色的子序列就是我们要找的序列。

所以整个数组的元素就可以分为两类,一类是属于最终的目标序列,一类是不属于最终的目标序列。
那我们要怎么确定一个元素是否应该选取到目标序列呢?咱们还是从小规模开始分析吧,懂的都懂(小K式思维法)。

03

小规模分析

3.1

一个元素

如果只有一个元素,那自然是要选了,最大长度为1。

3.2

两个元素

如果再加第2个元素,满足递增子序列,两个都选,最大长度为2。

如果再加第2个元素是这样的,选了第1个就选不了第2个,不选第1个就可以选第2个。但怎么选都只能选1个,最大长度是1。

3.3

三个元素

如果选取了前面2个元素,再加第3个元素,已经无法再选取,最大长度为2。

如果前面只选取第1个元素,再加第3个元素,可以选取第3个元素,最大长度也为2。

请问你发现什么规律了吗?

因为是递增序列,所以一个元素能不能选,跟之前选择的最后一个元素有关。如果大于最后一个元素就可以选择,如果小于或等于就无法选择。

04

抽象分析

如果不考虑任何规律,每个元素可以选或不选, 个元素就有 种选取方法。当然要保证递增序列,就可以排除很多不合理的情况,但规模依然很大。

假设原问题已经找到了最大的子序列,现在我再给你加一个元素进来,选还是不选呢?

如果原问题最大长度为X,那选择最新的元素的前提就是最大长度能变成X+1,如果选了长度没变甚至更小那肯定就不选。说明新的元素一定要能接在之前的最优解后面才可选取。
数据规模每扩大一次,最优解也是在之前的最优解上面扩充。

再根据第3小节的分析,对于每一个最优解,其实我们并不关注前面的X-1个元素是怎么选择的,只关注第X个元素是选的啥,那就可以从小规模开始枚举,求出以每个元素作为结尾时的最大长度,这样就可以递推出更大规模的最优解,这其实就是动态规划的思想。

05

动态规划

表示以第 个元素为结尾,能得到的最大的长度,那么 一定是从之前的某个最优解递推过来。
即。

代码实现

void dp() {
    int a[100], f[100], ans = 0;
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
        f[i] = 1;
        for (int j = 0; j < i; ++j) {
            if (a[j] < a[i]) {
                f[i] = max
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值