链接:牛牛的数列_牛客笔试题_牛客网
来源:牛客网
牛牛现在有一个n个数组成的数列,牛牛现在想取一个连续的子序列,并且这个子序列还必须得满足:最多只改变一个数,就可以使得这个连续的子序列是一个严格上升的子序列,牛牛想知道这个连续子序列最长的长度是多少。
输入描述:
输入包括两行,第一行包括一个整数n(1 ≤ n ≤ 10^5),即数列的长度; 第二行n个整数a_i, 表示数列中的每个数(1 ≤ a_i ≤ 10^9),以空格分割。
输出描述:
输出一个整数,表示最长的长度。
示例1
输入
6 7 2 3 1 5 6
输出
5
算法思路:
我们看整个数组,会发现最大的“牛牛的数列”无非就三种情况(设当前最大为ans,ans初始值为0)
(1)当前数字k之前的有递增序列大小为p,于是ans=max(ans,p+1)
(2)当前数字k之后的有递增序列大小为q,于是ans=max(ans,q+1)
(3)当前数字k前后都是递增序列,前面为p,后面为q,于是ans=max(ans,p+q+1);
那么我们考虑对数组从左往右遍历求出每个位置的最长升序子序列长度la[i],从右往左遍历求出每个位置从后往前连续降序子序列长度ra[i]
发现ans最大是在a[i]=1处,它前面q=la[i-1],p=ra[i+1],所以ans=max(ans,la[i-1]+ra[i+1]+1)=5
#include<stdio.h>
int max(int a, int b){
if(a>b)
return a;
else
return b;
}
int main(){
int n,a[100005],la[100005],ra[100005],ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){ //求la数组,i=0时候初始为0
if(a[i]>a[i-1])
la[i]=la[i-1]+1;
else
la[i]=1;
}
for(int i=n;i>0;i--){ //求ra数组,i=0时候初始为0
if(a[i+1]>a[i])
ra[i]=ra[i+1]+1;
else
ra[i]=1;
}
for(int i=1;i<=n;i++){
ans = max(ans,ra[i+1]+1); //情况一:当前数字k之前的有递增序列大小为p,于是ans=max(ans,p+1)
ans = max(ans,la[i-1]+1); //情况二:当前数字k之后的有递增序列大小为q,于是ans=max(ans,q+1)
if(a[i+1]>=a[i-1]+2) //情况三:当前数字k前后都是递增序列,前面为p,后面为q,于是ans=max(ans,p+q+1)
ans=max(ans,la[i-1]+ra[i+1]+1);
}
for(int i=1;i<=n;i++){ //防止整个序列是有序的
ans=max(ans,max(la[i],ra[i]));
}
printf("%d",ans);
return 0;
}