C++最长上升子序列

C++最长上升子序列现有数列a1,a2,a3……aN。在其中找到严格递增序列ai1,ai2,ai3,……aiK(1<=i1

大家好,又见面了,我是你们的朋友全栈君。

最长上升子序列简介

题目描述
现有数列a1,a2,a3……aN。在其中找到严格递增序列ai1,ai2,ai3,……aiK(1 <= i1 < i2 < i3 < …… < iK <= N),请找出序列a的最长上升子序列的长度,既K的最大值。

输入格式
第一行:一个整数N。
第二行:N个整数a1,a2,a3……aN。

输出格式
一行,最大的K。

输入样例

10
5 10 8 9 7 10 13 12 25 13

输出样例

6

二维动态规划解法

提到DP,就一定就要去想:状态、转移方程、初值和答案了。

  1. 状态:dp[i]指在1~i这i个数中,必须包含a[i]这个数的最长上升子序列。
  2. 转移方程:if(a[j] < a[i]) dp[i] = max(dp[i], dp[j] + 1)(1 <= j <= i – 1)
    其实这个的意思就是:如果说在1~(i – 1)这(i – 1)个数中,a[j] < a[i],a[i]就可以接上a[j],形成一个比dp[j]又多了1的递增序列,因此每次判断并取最大值就行了。
  3. 初值:dp[i] = 1(一个数本身就是一个递增序列)。
  4. 答案:max{dp[i]}

(PS:NR指序列长度的上限)

# include <cstdio>
# include <iostream> 
# include <cmath>
# include <cstring>
# include <algorithm>

using namespace std;

# define FOR(i, a, b) for(int i = a; i <= b; i++)
# define _FOR(i, a, b) for(int i = a; i >= b; i--)

const int NR = 100000;

int n, ans;
int a[NR + 2], dp[NR + 2];

int main()
{ 
   
    scanf("%d", &n);
    FOR(i, 1, n) scanf("%d", &a[i]);
    FOR(i, 1, n) dp[i] = 1;
    FOR(i, 2, n){ 
   
        FOR(j, 1, i - 1)
            if(a[j] < a[i]) dp[i] = max(dp[i], dp[j] + 1);
        ans = max(ans, dp[i]);
    }
    printf("%d\n", ans);
    return 0;
}

贪心二分查找解法

二维动态规划的时间复杂度为On^2,太多了,我们想去优化,可是我们发现直接在二维上改好像改不了,没办法,只好再想一个新的方法了。

这次,我们开一个新的数组f,f[i]表示当上升子序列长度为i时,此子序列最后一个元素的最小值。我们会发现这个f数组是随着i值的增加,f[i]不断增大的单调队列。因为如果长度为i的上升子序列最后一位都为f[i]了,那长度(i + 1)的最后一位至少也得是f[i] + 1了吧。

这样我们从1到n一个元素一个元素的分析,当到了第i个元素时,我们在f数组中找第一个大于等于a[i]的f[k],这就代表长度为(k – 1)的上升子序列最后一位的最少值是f数组中最后一个小于a[i]的数,所以就让我们就可以把a[i]放到长度为(k – 1)的这个上升子序列的后面,形成一个新的长度为k的这个上升子序列,接下来更新f[k]的值f[k] = min(f[k], a[i])可我们发现我们找f[k]时就说了f[k]是f数组中第一个大于等于a[i]的数,所以直接f[k] = a[i]就好了。

下图仅供参考。
在这里插入图片描述
其中,在f数组中找第一个大于等于a[i]的f[k]时,可以用到二分查找函数中的lower_bound函数。

如果你还没有学过lower_bound可以到此网站学习lower_bound函数的用法
https://blog.csdn.net/SkeletonKing233/article/details/99479707

这样时间复杂度就从On^2降到了Onlogn,大大减少了时间的消耗。

以下为代码:

# include <cstdio>
# include <iostream> 
# include <cmath>
# include <cstring>
# include <algorithm>

using namespace std;

# define FOR(i, a, b) for(int i = a; i <= b; i++)
# define _FOR(i, a, b) for(int i = a; i >= b; i--)

const int NR = 100000;

int n, ans;
int a[NR + 2];
int f[NR + 2];

int main()
{ 
   
	scanf("%d", &n);
 	FOR(i, 1, n) scanf("%d", &a[i]);
 	f[0] = -2e9;
 	FOR(i, 1, n){ 
   
 		int k = lower_bound(f, f + ans + 1, a[i]) - f;
 		f[k] = a[i];
 		ans = max(ans, k);
	}
	printf("%d\n", ans);
	return 0;
}

最长下降、不上升、不下降子序列

剩下的这三种都与第一种十分相像:

  • 最长不下降子序列:就是把FOR循环中的lower_bound函数改成upper_bound函数。
  • 最长下降子序列:就是把FOR循环前的f[0] = -2e9改成f[0] = 2e9之后再在全局写一个比较函数cmp,并在lower_bound函数中做为第4个参数引用
  • 最长不上升子序列:就是先改成最长下降子序列,之后再把FOR循环中的lower_bound函数改成upper_bound函数。

PS:cmp函数的写法:

bool cmp(int x, int y){ 
   
	return x > y;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/131509.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • c语言运行后电脑很卡,如何让电脑提速,电脑卡是什么原因?

    c语言运行后电脑很卡,如何让电脑提速,电脑卡是什么原因?前言昨天的文章被限制了,正在申诉刚好最近有网友问小编这样一个问题:花了六千买的独显笔记本,用了才一年就卡的不行了,请问电脑卡是什么原因?小编对电脑还算颇有研究,看了网友电脑配置并不算低,导致电脑卡的原因主要在于系统优化与一些硬件方面的问题,下面小编就来说说如何让电脑提速。正文电脑卡是什么原因?导致电脑卡的原因有很多,综合来看,无非就是软件与硬件的问题。其中,软件层面主要是系统优化,硬件方面则主要是…

    2022年6月7日
  • 高可用高性能分布式文件系统FastDFS实践Java程序

    高可用高性能分布式文件系统FastDFS实践Java程序

    2022年3月13日
  • PAT乙级题目答案汇总 PAT (Basic Level) Practice (中文)[通俗易懂]

    PAT乙级题目答案汇总 PAT (Basic Level) Practice (中文)[通俗易懂]题目列表:标号题目链接分数博客链接完成时间1001害死人不偿命的(3n+1)猜想151001害死人不偿命的(3n+1)猜想(15分)2020/8/01

    2022年5月29日
  • win10双系统重装ubuntu_双系统win10无法启动

    win10双系统重装ubuntu_双系统win10无法启动&amp;amp;amp;amp;NBSP;&amp;amp;amp;amp;NBSP;&amp;amp;amp;amp;NBSP;&amp;amp;amp;amp;NBSP;这两天笔者安装win10+ubuntu16.04双系统,因为网络上能找到大量的资料,安装过程此处就不多讲。因为笔者电脑是华硕主板,bios默认设置为安全启动,笔者猜测会阻止加载ubuntu引导,导致双系统不能随意引导。先不管那么多,现在的问题是Ubuntu已经安装成功,开机直接进入win10,所以笔者的

    2022年10月21日
  • powerdesigner 画出 C++ UML 增加const,static,virtual属性

    powerdesigner 画出 C++ UML 增加const,static,virtual属性

    2022年3月13日
  • 腾讯重磅开源 DCache,分布式 NoSQL 存储系统

    腾讯重磅开源 DCache,分布式 NoSQL 存储系统开发四年只会写业务代码,分布式高并发都不会还做程序员?->>>受访嘉宾:山宝银|作者:h4cd当你在电商平台秒杀商品或者在社交网络刷热门话题的时候,可以很明显感受到当前网络数据流量的恐怖,几十万商品刚开抢,一秒都不到就售罄;哪个大明星出轨的消息一出现,瞬间阅读与转发次数可以达到上亿。作为终端用户的我们可能会思考,服务系统是怎么在这样严峻的流量环境中存活下来的。…

    2022年10月21日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号