最长****子序列

article/2025/9/28 10:09:26

(在研读大佬写的博客后,打算记录下自己学习过程)

 

通过最长上升子序列的拓展了解到,其实这是一个系列的问题主要代表有:

1 最长上升子序列

2 最长不上升子序列

3 最长下降子序列

4 最长不下降子序列

就以最长上升子序列为例。(注意:这里面说的子序列不连续的)

得到一个数组,求这个数组的最长上升子序列长度

3 1 2 1 8 5 6

可以直接看出来这个数组的最长上升子序列是1 2 5 6,其长度也就是4.一眼就能看出来,但是用代码该怎么实现呢?

介绍俩种方法:

dp思想 

只能用于数据小的情况,要不然会TLE

目前为止所接触的dp思想核心就在状态转移方程上。同时也用到了贪心的思想。在所有的上升序列中最开始的长度都是1(算上它自身)。那么这个时候就只要考虑以arr[i]结尾的子序列中使其最长即可。找到arr[i]然后在从头开始枚举,只要满足arr[j]<arr[i]都给他塞进去从而去取max值

brr[1]=1  (本身长度为1)

brr[2]=1;

brr[3]=2;

brr[4]=1;

brr[5]=3;

.......以此类推

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<stack>
#include<string>
#include<algorithm>
//#include<unordered_map>
#include<map>
#include<cstring>
//#include <unordered_set>
#include<queue>
#include<set>
#include<stdlib.h>
#define dbug cout<<"hear!"<<endl;
#define rep(a,b,c) for(ll a=b;a<=c;a++)
#define per(a,b,c) for(ll a=b;a>=c;a--)
#define no cout<<"NO"<<endl;
#define yes cout<<"YES"<<endl;
#define endl "\n"
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//priority_queue<int,vector<int>,greater<int> >q;
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> PII;
typedef pair<long double,long double> PDD;
const int N = 4e5 + 5;
const int  INF = 0x3f3f3f3f;
//const ll LINF=LLONG_MAX;
// ll gcdd(ll a, ll b)
// {
//       while(b^=a^=b^=a%=b);    
//       return a;
// }
// void add(ll a,ll w)
// {
//   noda[++idx].b=w;
//   noda[idx].ne=h[a];
//   h[a]=idx;
// }ll h[N],idx;
const ll mod =1000000007;
ll  t, n,a,b,c,d, m, x,y, k, cnt, ans, ant, sum,q,p,num;
ll arr[N],brr[N], crr[N];
bool book[N];int main()
{IOS;cin>>n;for(ll i=1;i<=n;i++){cin>>arr[i];}for(ll i=1;i<=n;i++)//最长上升子序列{brr[i]=1;for(ll j=1;j<i;j++){if(arr[i]>arr[j]){brr[i]=max(brr[i],brr[j]+1);}}}for(ll i=1;i<=n;i++)//最长下降子序列{brr[i]=1;for(ll j=1;j<i;j++){if(arr[i]<arr[j]){brr[i]=max(brr[i],brr[j]+1);}}}for(ll i=1;i<=n;i++)//最长不上升子序列{brr[i]=1;for(ll j=1;j<i;j++){if(arr[i]<=arr[j]){brr[i]=max(brr[i],brr[j]+1);}}}for(ll i=1;i<=n;i++)//最长不下降子序列{brr[i]=1;for(ll j=1;j<i;j++){if(arr[i]>=arr[j]){brr[i]=max(brr[i],brr[j]+1);}}}
}

 二分思想

用于处理大型数据

先来看例子

3 1 2 1 8 5 6

 1、如图所示,可以发现找到长度为1的上升子序列,若后面的数能接到3的后面,那么一定能接到1的后面,因为1比3更好,扩展度高

2、使用q[]存储所有不同长度的上升子序列结尾的最小值

3、进来一个数arr[i]时,通过二分在q[]中找到最大的小于arri的数,就能够将arri接到该数的后面,即更新q[r + 1] = arr[i]

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<stack>
#include<string>
#include<algorithm>
//#include<unordered_map>
#include<map>
#include<cstring>
//#include <unordered_set>
#include<queue>
#include<set>
#include<stdlib.h>
#define dbug cout<<"hear!"<<endl;
#define rep(a,b,c) for(ll a=b;a<=c;a++)
#define per(a,b,c) for(ll a=b;a>=c;a--)
#define no cout<<"NO"<<endl;
#define yes cout<<"YES"<<endl;
#define endl "\n"
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//priority_queue<int,vector<int>,greater<int> >q;
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> PII;
typedef pair<long double,long double> PDD;
const int N = 4e5 + 5;
const int  INF = 0x3f3f3f3f;
//const ll LINF=LLONG_MAX;
// ll gcdd(ll a, ll b)
// {
//       while(b^=a^=b^=a%=b);    
//       return a;
// }
// void add(ll a,ll w)
// {
//   noda[++idx].b=w;
//   noda[idx].ne=h[a];
//   h[a]=idx;
// }ll h[N],idx;
const ll mod =1000000007;
ll  t, n,a,b,c,d, m, x,y, k, cnt, ans, ant, sum,q,p,num;
ll arr[N],brr[N], crr[N];
bool book[N];int main()
{IOS;cin>>n;for(ll i=0;i<n;i++){cin>>arr[i];}/最长上升子序列ans=0;brr[0]=-2e9;for(ll i=0;i<n;i++){//手写二分ll l=0,r=ans;while(l<r){ll mid=l+r+1>>1;if(brr[mid]<arr[i]){l=mid;}else{r=mid-1;}}brr[r+1]=arr[i];ans=max(ans,r+1);/调用二分函数cnt=lower_bound(brr,brr+ans+1,arr[i])-brr;ans=max(ans,cnt);brr[cnt]=arr[i];}cout<<ans;/最长下降子序列ans=0;brr[0]=-2e9;for(ll i=0;i<n;i++){//手写二分ll l=0,r=ans;while(l<r){ll mid=l+r+1>>1;if(brr[mid]>arr[i]){l=mid;}else{r=mid-1;}}brr[r+1]=arr[i];ans=max(ans,r+1);}cout<<ans;/最长不下降序列ans=0;brr[0]=-2e9;for(ll i=0;i<n;i++){//手写二分ll l=0,r=ans;while(l<r){ll mid=l+r+1>>1;if(brr[mid]<=arr[i]){l=mid;}else{r=mid-1;}}brr[r+1]=arr[i];ans=max(ans,r+1);}cout<<ans;/最长不上升子序列ans=0;brr[0]=-2e9;for(ll i=0;i<n;i++){//手写二分ll l=0,r=ans;while(l<r){ll mid=l+r+1>>1;if(brr[mid]>=arr[i]){l=mid;}else{r=mid-1;}}brr[r+1]=arr[i];ans=max(ans,r+1);}cout<<ans;
}

   浅浅举个例子 

拦截导弹

某国为了防御敌国的导弹袭击,开发出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭,并观测到导弹依次飞来的高度,请计算这套系统最多能拦截多少导弹。拦截来袭导弹时,必须按来袭导弹袭击的时间顺序,不允许先拦截后面的导弹,再拦截前面的导弹。

Input

输入有两行,
第一行,输入雷达捕捉到的敌国导弹的数量k(k<=25),
第二行,输入k个正整数,表示k枚导弹的高度,按来袭导弹的袭击时间顺序给出,以空格分隔。

Output

输出只有一行,包含一个整数,表示最多能拦截多少枚导弹。

Sample

InputcopyOutputcopy
8
300 207 155 300 299 170 158 65
6

注意细节:后一发的导弹高度不能高于前一段也就是严格小于,所以就是求最大下降子序列

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<stack>
#include<string>
#include<algorithm>
//#include<unordered_map>
#include<map>
#include<cstring>
//#include <unordered_set>
#include<queue>
#include<set>
#include<stdlib.h>
#define dbug cout<<"hear!"<<endl;
#define rep(a,b,c) for(ll a=b;a<=c;a++)
#define per(a,b,c) for(ll a=b;a>=c;a--)
#define no cout<<"NO"<<endl;
#define yes cout<<"YES"<<endl;
#define endl "\n"
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//priority_queue<int,vector<int>,greater<int> >q;
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> PII;
typedef pair<long double,long double> PDD;
const int N = 4e5 + 5;
const int  INF = 0x3f3f3f3f;
//const ll LINF=LLONG_MAX;
// ll gcdd(ll a, ll b)
// {
//       while(b^=a^=b^=a%=b);    
//       return a;
// }
// void add(ll a,ll w)
// {
//   noda[++idx].b=w;
//   noda[idx].ne=h[a];
//   h[a]=idx;
// }ll h[N],idx;
const ll mod =1000000007;
ll  t, n,a,b,c,d, m, x,y, k, cnt, ans, ant, sum,q,p,num;
ll arr[N],brr[N], crr[N];
bool book[N];int main()
{IOS;cin>>n;for(ll i=0;i<n;i++){cin>>arr[i];}rep(i,1,n){brr[i]=1;rep(j,1,i){if(arr[i]<arr[j]){brr[i]=max(brr[i],brr[j]+1);}}}ans=0;rep(i,1,n){// cout<<brr[i]<<' ';ans=max(ans,brr[i]);}
cout<<ans;
}


http://chatgpt.dhexx.cn/article/d4VtbjiY.shtml

相关文章

最长公共子序列

最长公共子序列&#xff08;Longest Common Subsequence&#xff0c;简称 LCS&#xff09;是一道非常经典的面试题目&#xff0c;因为它的解法是典型的二维动态规划&#xff0c;大部分比较困难的字符串问题都和这个问题一个套路&#xff0c;比如说编辑距离。而且&#xff0c;这…

最长公共子序列(LCS) 过程图解

1.基本概念 首先需要科普一下&#xff0c;最长公共子序列&#xff08;longest common sequence&#xff09;和最长公共子串&#xff08;longest common substring&#xff09;不是一回事儿。什么是子序列呢&#xff1f;即一个给定的序列的子序列&#xff0c;就是将给定序列中零…

最长子序列问题详解

提到最长子序列问题&#xff0c;想必大家都不陌生&#xff0c;今天我主要想分享一下我对子序列问题的一些理解&#xff1a; 先拿最长上升子序列问题来说吧&#xff1a; 很明显这是一个动态规化问题&#xff0c;仔细想想也不难得出其状态转移方程 首先介绍一下dp[]数组的含义…

如何查看pip版本

Windows系统如何查看pip版本 直接运行pip show pip

python之pip版本问题

我们在默认安装python软件之后&#xff0c;其自行安装的pip的版本可能比较落后。我们使用pip安装模块的时候经常提示安装失败&#xff0c;查看安装失败原因&#xff0c;部分是因为pip不是最新版本需要升级版本才能继续安装&#xff0c;因此写下一点小心得&#xff0c;让我们都能…

pip 查看可安装版本

pip 查看可安装版本 pip版本&#xff1a; pip -V pip 20.1.1 from /usr/lib/python2.7/site-packages/pip (python 2.7) 查看pip可安装版本 import pip._internal.utils.compatibility_tags print(pip._internal.utils.compatibility_tags.get_supported())

python如何查看pip版本并且升级pip

第一次写Python的学习经历 我之前也安装过Python,今天&#xff0c;终于重新安装了64位的windows的Python,于是在命令行输入&#xff1a;“pip list”出现以下的提示&#xff1a; 这个提示以前也出现过&#xff0c;但是看不懂&#xff0c;也不知道怎么处理&#xff0c;然后又胡…

python pip 查找指定安装包版本信息

一、windows操作系统 pip list | findstr 查找的包&#xff08;支持模糊查询&#xff09;例&#xff1a; pip list | findstr huawei结果&#xff1a; 二、linux操作系统 pip list | grep 查找的包&#xff08;支持模糊查询&#xff09;

更新pip版本

更新pip版本 从报错来看是因为pip版本为20.2.3&#xff0c;但当前可用版本是21.0.1 python -m ensurepippython -m pip install --upgrade pippip list设置镜像默认源 #临时使用 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple some-package #设置默认源 pip inst…

拉取的docker镜像中更换python以及pip版本

场景&#xff1a; 需要tensorflow1.10 python3.6 的环境&#xff0c;但是拉取的tf1.10镜像中&#xff0c;默认python版本是3.5 &#xff0c;此时我们需要安装python3.6版本&#xff0c;将python命令的软连接删除&#xff0c;并且指向新安装的3.6&#xff0c;且pip的连接也应该…

Python查看所有版本及pip

1、查看python默认版本&#xff1a; python --version &#xff08;默认的版本我改为了python3&#xff0c;所以结果是3.7的&#xff09; 2、查看另外安装的2.7的版本&#xff1a; python2.7 --version 3、查看python安装路径&#xff1a; 1&#xff09;终端输入python2.7回…

python降低pip版本

场景&#xff1a; 使用Pycharm开发时&#xff0c;经常会遇到因为pip版本过高而导致下载第三方库失败的情况 解决方案&#xff1a; 经查资料&#xff0c;发现可以通过降低pip的版本来解决问题 如下&#xff1a; 第一种方法&#xff1a;使用Terminal命令行进行降级 python -m pip…

Linux查看pip版本号的命令,pip 经常使用命令及控制台怎么查看python 及pip 和已安装包版本号...

在使用python的时候&#xff0c;常常使用到pip这个工具&#xff0c;能够很方便的线上安装依赖库&#xff0c;固然pip还有不少参数均可以帮咱们去查询一些库信息&#xff0c;在安装python的时候&#xff0c;下载带有pip的安装包就能够直接安装pip啦&#xff0c;固然没有带pip的&…

查看pip版本 及升级pip命令报错解决办法

pip install pytest_ordering时警告&#xff0c;pip版本过低 WARNING: You are using pip version 21.1.3; however, version 21.2.4 is available. You should consider upgrading 1、查看pip&#xff1a; pip show pip 2、升级pip&#xff1a;python -m pip install --upg…

最新升级pip命令,查看pip版本命令,pycharm升级pip命令,推荐收藏关注不迷路

1. 查看pip版本命令&#xff1a;pip -V &#xff0c;可以看看以下代码运行完过后&#xff0c;自己的pip版本有没有升级成功 python升级pip命令&#xff1a;打开命令行输入 python -m pip install -U pip 回车 pycharm升级pip命令 &#xff1a;打开命令行输入&#xff1a; py…

[Python]pip查找包的历史版本

pip查找包的历史版本 场景&#xff1a;在一些时候通过pip install xxx 安装第三方库的时候默认情况下安装最新版本&#xff0c;由于是最新版本有个稳定性就不得不考虑其中&#xff0c;所以部分场景会存在一些bug这就要求我们安装历史版本&#xff0c;对一些更新频率比较高的三…

已解决正确查看pip版本、查看pip帮助命令

已解决&#xff08;pip查看版本报错&#xff09;Usage&#xff1a;pip [options] no such option: —verson 文章目录 报错代码报错翻译报错原因解决方法千人全栈VIP答疑群联系博主帮忙解决报错 报错代码 粉丝群一个小伙伴想用pip查看版本报错&#xff0c;但是发生了报错&#…

解决OpenSSL SSL_read: Connection was reset, errno 10054

报错问题&#xff1a; fatal: unable to access ‘https://github.com/Sunyt1992/ref-comet.git/’: OpenSSL SSL_read: Connection was reset, errno 10054 OpenSSL SSL_read:连接已重置&#xff0c;错误号10054 字面意思&#xff1a;服务器的SSL证书灭有经过第三方机构的签署…

TCP 10054

2019独角兽企业重金招聘Python工程师标准>>> TcpSocket:Connection reset by peer 10054 10054 ConnectionReset 客户端网络情况不好的条件下&#xff0c;比如正在下载其他东西&#xff0c;而服务器又有心跳超时处理&#xff0c;客户端的心跳迟迟发不上去&#xff0…