牛牛的数列java_【算法】算法测试题5:牛牛的数列:最长一连子序列

问题形貌

牛牛如今有一个n个数构成的数列,牛牛如今想取一个一连的子序列,而且这个子序列还必须得满足:最多只转变一个数,就可以使得这个一连的子序列是一个严厉上升的子序列,牛牛想晓得这个一连子序列最长的长度是多少。

输入形貌

输入包含两行,第一行包含一个整数n(1 ≤ n ≤ 10^5),即数列的长度;

第二行n个整数a_i, 示意数列中的每一个数(1 ≤ a_i ≤ 10^9),以空格支解。

输出形貌

输出一个整数,示意最长的长度。

示例1

输入

6

7 2 3 1 5 6

输出

5

解题思绪

剖析:这道问题看上去没法动手,就当进修一个思绪吧,起首依据当前数组顺着求一遍以每一个位置作为末端的一连最长递增子序列的长度值,再逆着求解以每一个元素作为开首的一连最长递增子序列的长度值,然后依据这两组值来找衔接点。详细就拿体重的例子来讲,此时数组arr为

7 2 3 1 5 6,我们定义两个数组left

和right,left数组示意正着求以每一个元素作为末端的最长递增子序列的长度,而right数组示意逆着以每一个元素作为开首的一连最长递增子序列的长度值,所以可以晓得left[0]=1,示意以7末端的现在最长的一连递增子序列的长度值就是1,顺次left[1]=1,left[2]=2,left[3]=1,left[4]=2,left[5]=3;

而right[5]=1,right[4]=2,right[3]=3,right[2]=1,right[1]=2,right[0]=1;好了,到此为止两个辅佐的数组已求出,接下来就要找衔接点了,是如许的,依据问题意义,我们要找一个子序列,而且之多转变一个数就可以构成严厉的一连递增子序列,所以我们先盯住数组中2这个数,我们发现以7末端的最长的一连递增子序列的长度为left[0],而以3开首的一连递增子序列长度为right[2],如许,我们实在不必管7和3之间的数到底是多少,是2也好,不是2也好,只需2前面的数7可以严厉小于2背面的数3,申明经由过程转变7和3之间这个数至适宜的数值则,这两部分就可以连成一个一连的严厉递增子序列,一切,我们遍历一切如许的点,纪录满足前提的最大的长度再加1即可。

JavaScript代码

JavaScript代码1(雏形)

let n = parseInt(readline());

let t1 = readline();

let t2 = new String(t1);

let line = t2.split(" ");

let arr = new Array();

for(let i = 0; i < line.length; i++){

arr[i] = parseInt(line[i]);

}

let left = new Array(n);

let right = new Array(n);

let ans = 0;

for(let i = 0; i < arr.length; i++){

left[i] = computeLeft(i, arr);

}

for(let i = arr.length - 1; i >= 0; i--){

right[i] = computeRight(i, arr);

}

for(let i = 1 ; i < arr.length-1; i++){

if(arr[i-1] < arr[i+1]){

let sum = left[i-1] + right[i+1];

if(sum > ans){

ans = sum;

}

}

}

print(ans+1);

function computeLeft(pos, arr){

let count = 1;

for(let i = pos; i > 0; i--){

if(arr[i] > arr[i-1]){

count++;

}else{

return count;

}

}

return count;

}

function computeRight(pos, arr){

let count = 1;

for(let i = pos; i < arr.length-1; i++){

if(arr[i] < arr[i+1]){

count++;

}else{

return count;

}

}

return count;

}

JavaScript代码2(优化)

let n = parseInt(readline());

let t1 = readline();

let t2 = new String(t1);

let line = t2.split(" ");

let arr = new Array();

for(let i = 0; i < line.length; i++){

arr[i] = parseInt(line[i]);

}

let left = new Array(n);//以arr[i]末端的一连序列长度

let right = new Array(n);//以arr[i]开首的一连序列长度

let ans = 0;

left[0] = 1;

right[0] = 1;

for(let i = 1; i < arr.length; i++){

if(arr[i] > arr[i-1]){

left[i] = left[i-1] + 1;

}else{

left[i] = 1;

}

//left[i] = computeLeft(i, arr);

}

for(let i = arr.length - 1; i >= 0; i--){

if(arr[i] < arr[i+1]){

right[i] = right[i+1]+1;

}else{

right[i] = 1;

}

//right[i] = computeRight(i, arr);

}

for(let i = 1 ; i < arr.length-1; i++){

if(arr[i-1] < arr[i+1]){

let sum = left[i-1] + right[i+1];

if(sum > ans){

ans = sum;

}

}

}

print(ans+1);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值