dp2.牛牛的数列

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

题目描述

牛牛现在有一个n个数组成的数列,牛牛现在想取一个连续的子序列,并且这个子序列还必须得满足:最多只改变一个数,就可以使得这个连续的子序列是一个严格上升的子序列,牛牛想知道这个连续子序列最长的长度是多少。

输入描述:

输入包括两行,第一行包括一个整数n(1 ≤ n ≤ 10^5),即数列的长度;
第二行n个整数a_i, 表示数列中的每个数(1 ≤ a_i ≤ 10^9),以空格分割。

输出描述:

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

示例1

输入

6

7 2 3 1 5 6

输出

5

示例2

输入

6

1 2 4 2 5 6

输出

4


定义[start1, end1]为第一个严格递增子序列,[start2, end2]为第二个严格递增子序列,start2 = end1 + 1;

当start1 == end1, start2 == end2时,说明严格递增子序列只有1个数;

两个严格递增子序列可以合并的情况:

1. start1 == end1,第一个严格递增子序列只有一个数,可以变化该数,使得这个数小于第二个严格递增子序列的最小的数,也就是nums[start2];

2. start2 == end2,第二个严格递增子序列只有一个数,可以变化该数,使得这个数大于第一个严格递增子序列的最大的数,也就是nums[end1];

3. 当start1 != end1时,说明第一个严格递增子序列至少有2个数,当start2 != end2时,说明第二个严格递增子序列至少有2个数;

    当第二个严格递增子序列的第二个数 > 第一个严格递增子序列最大的数 + 1,即nums[start2 + 1] > nums[end1] + 1,可以把nums[start2]变化,

    使得这两个子序列可以合并;

    当第一个严格递增子序列的倒数第二个数 < 第二个严格递增子序列最小的数 - 1,即nums[end1 - 1] < nums[start1] - 1,可以把nums[end1]变化,

    使得这两个子序列可以合并;

两个严格递增子序列不能合并时:

此时的答案是这两个子序列长度最长的长度 + 1,1是较短的子序列的拿出最大的数或者最小的数拼接到长的序列上。

迭代更新[start1, end1]和[start2, end2],找到答案最大的值。

#include <iostream>
#include <vector>

using namespace std;

int solution(vector<int> &nums) {
    int n = nums.size();
    if (n <= 0)
        return 0;
    int res = 0;
    int start1 = 0, end1 = start1;
    while (end1 < n - 1 && nums[end1] < nums[end1 + 1])
            end1++;
    // end1 == n - 1代表整个数组严格递增
    if (end1 == n - 1)
        return end1 - start1 + 1;
    // end1 < n - 1 保证[start2, end2]至少有数字
    while (end1 < n - 1) {
        int start2 = end1 + 1;
        int end2 = start2;
        while (end2 < n - 1 && nums[end2] < nums[end2 + 1])
            end2++;
        if (start1 == end1 || start2 == end2 || nums[start2 + 1] - nums[end1] > 1 || nums[start2] - nums[end1 - 1] > 1)
            res = max(res, end2 - start2 + end1 - start1 + 2);
        else 
            res = max(max(end2 - start2, end1 - start1) + 2, res);
        start1 = start2;
        end1 = end2;
    }
    return res;
}

int main() {
    int n;
    cin >> n;
    vector<int> nums(n);
    for (int i = 0; i < n; i++) {
        cin >> nums[i];
    }
    cout << solution(nums) << endl;
    return 0;
}

来源于我看到的一篇题解,感觉方法很好,讲解的也很仔细,题解人:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值