题解 | #牛牛的数列#

牛牛的数列

https://ac.nowcoder.com/acm/problem/13134

定义[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;
}





全部评论
主要思路:用两个指针分别指向子串的开头和结尾,分别找到两个子串的结束位置。然后根据两个子串之间的关系来更新最长子串的长度。 具体实现: 1.如果数组长度小于等于0,则返回0。 2.初始化变量res为0,start1和end1指针都指向数组的第一个元素。 3.首先找到第一个子串的结尾位置end1,在子串严格递增时一直向后移动end1指针。 4.如果发现整个数组是严格递增的,则直接返回整个数组的长度。 5.接下来寻找另一个子串的开始位置start2,从end1+1开始,然后找到这个子串的结尾位置end2,同样也是在子串严格递增的情况下一直向后移动end2指针。 6.然后分别判断两个子串之间的关系,并根据不同的情况来更新最长子串的长度: ①如果两个子串之间不存在空隙,则直接更新最长子串的长度,即res=max(res,end2-start2+end1-start1+2)。 ②如果两个子串之间有空隙,则更新最长子串的长度为两个子串中长度最长的那个加上1,即res=max(res,max(end2-start2,end1-start1)+2)。 7.最后更新start1和end1指针为start2和end2,继续寻找下一个符合条件的子串,直到end1指向数组的最后一个元素为止。 8.返回最长子串长度res即可。 时间复杂度:O(n)
点赞 回复 分享
发布于 2023-04-12 23:16 广东

相关推荐

Twilight_m...:表格简历有点难绷。说说个人看法: 1.个人基本情况里好多无意义信息,什么婚姻状况、健康状况、兴趣爱好、户口所在地、身份证号码、邮政编码,不知道的以为你填什么申请表呢。 2.校内实践个人认为对找工作几乎没帮助,建议换成和测开有关的项目,实在没得写留着也行。 3.工作经历完全看不出来是干什么的,起码看着和计算机没啥关系,建议加强描述,写点你在工作期间的实际产出、解决了什么问题。 4.个人简述大而空,看着像AI生成,感觉问题最大。“Python,C,C++成为我打造高效稳定服务的得力工具”、“我渴望凭借自身技术知识与创新能力,推动人工智能技术的应用发展,助力社会实现智能化转型”有种小学作文的美感。而且你确定你个人简述里写的你都会嘛?你AI这块写的什么“深入研究”,发几篇顶会的硕博生都不一定敢这么写。而且你AI这块的能力和软测也完全无关啊。个人简述建议写你对哪些技术栈、哪些语言、哪些生产工具的掌握,写的有条理些,而且最好是和测开强相关的。
点赞 评论 收藏
分享
评论
6
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务