首页 > 试题广场 >

牛牛的数列

[编程题]牛牛的数列
  • 热度指数:5466 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
牛牛现在有一个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即可。https://blog.csdn.net/wwe4023...

代码

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);
发表于 2018-08-31 13:26:43 回复(0)
思路来自于 不死大金刚 可以参考他的java代码!
js完整代码如下:
process.stdin.resume();
process.stdin.setEncoding('ascii');
   
var input = "";
var input_array = "";
var all, arr, tmp = [], cur;
var getMaxIncreaseLen = function(arr){
    var index = 1,
        len = arr.length,
        res = [];

    // 头部
    res[0] = 2; // 赋值为最小值2.
    if(arr[index] > arr[index-1]){
        index++;
        while(index < len){
            if(arr[index] > arr[index-1]){
                res[0]++;
                index++;
            }else{
                index++;
                break;
            }
        }
    }
    if(res[0] > 2 || arr[1] > arr[0]){
        // 首部出现的情况:8 7 6。。或者 8 9 6。。
        res[0]++;
    }
    if(index === len && arr[len-1] > arr[len-2]){// 连续上升
        // 后面的条件是以防出现1 2 3 4 5 4这种情况。
        return len;
    }

    // 尾部
    res[len-1] = 2;
    index = len-2;
    if(arr[index] < arr[index+1]){
        index--;
        while(index >= 0){
            if(arr[index] < arr[index+1]){
                index--;
                res[len-1]++;
            }else{
                break;
            }
        }
    }
    if(res[len-1] > 2 || arr[len-2] < arr[len-1]){
        res[len-1]++;
    }

    // 中间部分,i: [1, len-2]
    var pre, cur, next;
    for(var i = 1, leng = len-2; i <= leng; i++ ){
        pre = arr[i-1];
        cur = arr[i];
        next = arr[i+1];
        if(next - pre >= 2){
            // 三种情况:1 2 4 或者 4 2 7 或者 2 8 7
            if(cur < next && cur > pre){
                res[i] = 4; // 长度最小为4,因为还有一次的调整机会
            }else{
                res[i] = 3;
            }
            for(var j = i-2; j >= 0; j--){
                if(arr[j] < arr[j+1]){
                    res[i]++;
                }else{
                    break;
                }
            }
            for(j = i+2; j < len; j++){
                if(arr[j] > arr[j-1]){
                    res[i]++;
                }else{
                    break;
                }
            }
        }else{
            // 两种情况 :5 3 2 或者 7 1 8
            res[i] = (next - pre === 1) ? 3 : 2;
        }
    }
    return Math.max.apply(Math, res);
}   
process.stdin.on('data', function (data) {
    input += data;
});
   
process.stdin.on('end', function () {
    input_array = input.split('\n')[1].split(' ');
    input_array.forEach(function(ele, i){
        input_array[i] = +ele;
    });
    console.log(getMaxIncreaseLen(input_array));
});
发表于 2017-06-18 16:39:18 回复(0)

热门推荐

通过挑战的用户

牛牛的数列