题目描述
牛牛现在有一个n个数组成的数列,牛牛现在想取一个连续的子序列,并且这个子序列还必须得满足:最多只改变一个数,就可以使得这个连续的子序列是一个严格上升的子序列,牛牛想知道这个连续子序列最长的长度是多少。
输入描述:
输入包括两行,第一行包括一个整数n(1 ≤ n ≤ 10^5),即数列的长度;
第二行n个整数a_i, 表示数列中的每个数(1 ≤ a_i ≤ 10^9),以空格分割。
输出描述:
输出一个整数,表示最长的长度。
示例1
输入
6
7 2 3 1 5 6
输出
5
用两个数组left和right分别记录以每个元素为末端和以每个元素为首端的最长子序列长度。用res来表示当前最长子序列长度。
以此题为例:对于序列7 2 3 1 5 6。
left[0]表示以元素7为末端的单调递增序列的长度,很显然left[0]=1…left[ ]数组最后结果为1 1 2 1 2 3。
同理:right[ ]数组最后结果为1 2 1 3 2 1。
此时最长长度res=3。这是不改变序列中的元素最长子序列长度,我们还应当考虑改变一个元素后此时的子序列长度是否是最长的且满足单调递增。
我们只需要考虑这个需要改变的元素后一个元素和前一个元素之间的差是否大于或者等于二,这样在改变这个元素为其它值的时候,才能满足比前一个大比后一个小,即改变后的序列为单调递增。
package NEWCODE.test;
import java.util.Arrays;
import java.util.Scanner;
public class NC13134 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int a[]=new int[100001];
int left[]=new int[100001];
int right[]=new int [100001];
Arrays.fill(a,1);
Arrays.fill(left,1);
Arrays.fill(right,1);
for(int i=0;i<n;i++)
a[i]=sc.nextInt();
// left数组记录的是以每个元素为末端的单调递增子序列的最长长度
// right数组记录的是以每个元素为首端的单调递增子序列的最长长度
for(int i=1;i<n;i++)
{
if(a[i]>a[i-1])
left[i]=left[i-1]+1;
}
for(int i=n-2;i>=0;i--)
{
if(a[i]<a[i+1])
right[i]=right[i+1]+1;
}
// 测试实例:
// 6
// 7 2 3 1 5 6
// left,right结果:112123 121321
// for(int i=0;i<n;i++)
// System.out.print(left[i]);
// System.out.println();
// for(int i=0;i<n;i++)
// System.out.print(right[i]);
// 找最大字符串长度
int res=1;
for(int i=0;i<n;i++)
{
res=Math.max(res,left[i]);
res=Math.max(res,right[i]);
if(i==0&&a[i+1]>=2)
res=Math.max(res,right[i+1]+1);
else
{
if(a[i+1]-a[i-1]>=2)
res=Math.max(res,left[i-1]+right[i+1]+1);
}
}
System.out.println(res);
}
}
``