C++ 最长连号

本文介绍了如何解决一个编程问题,即给定一个正整数序列,找到其中最长的连续自然数连号。提供了输入和输出样例,并给出了C++参考代码。讨论了数据规模限制为10000以内,每个数在1到10亿之间的约束条件。


一、题目描述

最长连号

题目描述

输入长度为 n n n 的一个正整数序列,要求输出序列中最长连号的长度。

连号指在序列中,从小到大的连续自然数。

输入格式

第一行,一个整数 n n n

第二行, n n n 个整数 a i a_i ai,之间用空格隔开。

输出格式

一个数,最长连号的个数。

样例 #1

样例输入 #1

10
1 5 6 2 3 4 5 6 8 9

样例输出 #1

5

提示

数据规模与约定

对于 100 % 100\% 100% 的数据,保证 1 ≤ n ≤ 1 0 4 1 \leq n \leq 10^4 1n104 1 ≤ a i ≤ 1 0 9 1 \leq a_i \leq 10^9 1ai109


二、参考代码

#include <iostream>

using namespace std;
const int maxn = 10001;
int arr[maxn];


int main(void) {
    
    int n;
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        cin >> arr[i];
    }
    int cnt = 1;
    int max = 0;
    for (int i = 0; i < n - 1; i++)
    {
        if (arr[i + 1] - arr[i] == 1)
        {
            cnt++;
        }
        else
        {
            cnt = 0;
        }

        if (cnt > max)
        {
            max = cnt;
        }
    }
    cout << ++max << endl;
}



<think>嗯,用户让我用C++编程,输入一个正整数序列,然后输出最长连号的长度。首先,我得明确什么是连号连号应该是指连续递增的相邻元素,比如1,2,3或者5,6,7这样的,每个数比前一个大1。那最长连号就是这样的连续序列中最长的那个长度。 首先,我需要考虑怎么处理输入。用户输入的序列长度是n,所以程序需要先读取n,然后读取n个正整数。可以用cin来读取输入,存储到一个数组或者vector里。 接下来,如何找出最长连号呢?我的思路是遍历整个序列,比较当前元素和前一个元素的差是否为1。如果是的话,当前连号长度加1;否则,重置当前长度为1(因为单个元素本身也算长度为1的连号)。同时,要维护一个最大长度的变量,每次更新当前长度时比较并更新最大值。 比如,序列是1,2,3,4,2,3。遍历时: 1和2差1,当前长度变2; 2和3差1,当前长度3; 3和4差1,当前长度4; 4和2差-2,重置为1; 2和3差1,当前长度2。 所以最大长度是4。 需要注意的是,如果整个序列都是连号,比如n=5,1,2,3,4,5,那么长度是5。而如果序列只有一个元素,n=1,那么直接输出1。 可能的边界情况包括:n=0?但题目说是正整数序列,所以n应该至少是1。此外,序列中的数是否可能重复?比如3,5,5,这里的5和5差0,不算连号,所以中间会断开,当前长度重置为1。 那程序的大致步骤是: 1. 读取n。 2. 读取n个数存入数组。 3. 初始化max_len和current_len为1,因为至少有一个元素。 4. 遍历数组从第二个元素开始,比较当前和前一个的差是否为1。 5. 根据情况更新current_len和max_len。 6. 最后输出max_len。 测试一下这个逻辑。比如测试用例1: 输入: 5 1 2 3 4 5 输出应该是5。程序运行会正确。 测试用例2: 输入: 6 1 3 5 7 9 11 每个相邻差2,所以每个连号都是1,所以输出1。 测试用例3: 输入: 5 5 4 3 2 1 相邻差都是-1,所以每个连号都是1,输出1。 测试用例4: 输入: 7 3 4 5 4 5 6 7 这里3,4,5是连号,长度3;然后4,5,6,7是连号,长度4。所以输出4。 那在遍历的时候,每次current_len递增,当遇到差不是1的时候,current_len重置为1。同时每次都要比较max_len和current_len,取最大值。 那在代码中,可以用一个循环,从第二个元素开始,i=1到i<n。比较arr[i]和arr[i-1]是否差1。如果是,current_len++;否则,current_len=1。每次循环都检查max_len是否需要更新。 这样就能得到正确结果了。 现在考虑代码的编写。用C++的话,可以这样: #include <iostream> using namespace std; int main() { int n; cin >> n; int arr[n]; // 但注意C++中变长数组可能不被所有编译器支持,比如MSVC。所以最好用动态数组或者vector。 // 所以更安全的写法是用vector<int> arr(n); 然后读取。 for(int i=0; i<n; i++){ cin >> arr[i]; } if(n ==0) { // 但题目说是正整数序列,n应该>=1 cout << 0 << endl; return 0; } int max_len =1; int current_len =1; for(int i=1; i<n; i++){ if(arr[i] == arr[i-1]+1){ current_len++; if(current_len > max_len){ max_len = current_len; } } else { current_len =1; } } cout << max_len << endl; return 0; } 但是这里有个问题,当current_len在递增的时候,可能没有及时更新max_len。例如,当所有元素都是连号时,循环中每次current_len++都会检查是否超过max_len。是的,因为在每次current_len增加后,立即比较并更新max_len。比如在循环中,如果当前元素满足差1,current_len增1,然后马上比较是否超过max_len,是的话就更新。或者是不是应该每次循环不管是否进入if,都更新max_len? 比如,考虑序列1,2,3,4,5。第一次i=1,current_len变成2,max_len更新为2。i=2,current_len3,max更新。直到i=4的时候,current_len是5,最后max_len是5。这没问题。 但是如果代码写成在if里面才检查的话,会不会漏掉?比如当最后一个元素是连号的一部分,但循环结束后max_len可能没有被更新? 例如,假设在循环中只有在current_len增加的时候才会检查max_len,但是如果current_len在最后一次增加时已经是最大的,那么会被正确记录。例如,假设在循环结束后,max_len已经是正确的,因为每次遇到连号都会立即更新。 这样看来,代码是正确的。例如,假设序列是1,2,3,4,5,循环结束后max_len是5。如果是序列5,6,7,8,最后一次循环i=3,current_len=4,max_len会被更新为4。没问题。 那这个逻辑是正确的。那现在测试一些情况: 比如输入n=1,输出1,正确。 输入n=2,比如1 2,输出2;输入1 3,输出1。正确。 那这样的代码应该可以解决问题。不过需要注意变长数组的问题。例如,在C++标准中,int arr[n]如果n是变量,属于变长数组(VLA),而C++标准中不支持,只有C99支持。所以可能在某些编译器(如g++)允许,但其他如MSVC可能不行。所以更好的做法是用动态分配或者vector。 修改代码: #include <iostream> #include <vector> using namespace std; int main() { int n; cin >> n; vector<int> arr(n); for(int i=0; i<n; i++){ cin >> arr[i]; } if(n ==0) { // 根据题意,n>=1,但可以处理n=0的情况 cout << 0 << endl; return 0; } int max_len =1; int current_len =1; for(int i=1; i<n; i++){ if(arr[i] == arr[i-1]+1){ current_len++; if(current_len > max_len){ max_len = current_len; } } else { current_len =1; } } cout << max_len << endl; return 0; } 这样更安全,使用vector,避免VLA的问题。 那用户的问题应该解决了。可能还需要考虑输入是否正确,但题目假设输入都是正整数,所以无需处理非法输入。</think>要解决这个问题,我们需要找到正整数序列中最长的连续递增子序列(连号)的长度。以下是逐步解决方案: ### 步骤分析 1. **输入处理** 首先读取序列长度 $n$,然后读取 $n$ 个正整数存入数组或容器中。 2. **初始化变量** - `max_len`:记录当前找到的最长连号长度,初始值为 1(单个元素也算连号)。 - `current_len`:记录当前正在计算的连号长度,初始值为 1。 3. **遍历序列** 从第二个元素开始,依次比较当前元素与前一个元素是否差值为 1: - 若满足条件,则当前连号长度 `current_len` 加 1,并更新 `max_len`。 - 若不满足,重置 `current_len` 为 1。 4. **输出结果** 遍历完成后,`max_len` 即为最长连号的长度。 ### C++代码实现 ```cpp #include <iostream> #include <vector> using namespace std; int main() { int n; cin >> n; vector<int> arr(n); for (int i = 0; i < n; i++) { cin >> arr[i]; } int max_len = 1; // 至少长度为1(单个元素) int current_len = 1; for (int i = 1; i < n; i++) { if (arr[i] == arr[i - 1] + 1) { // 判断是否构成连号 current_len++; max_len = max(max_len, current_len); } else { current_len = 1; // 连号中断,重置长度 } } cout << max_len << endl; return 0; } ``` ### 示例说明 - **输入 1** ``` 5 1 2 3 4 5 ``` **输出**:5 **解释**:整个序列是连续递增的,连号长度为 5。 - **输入 2** ``` 6 1 3 5 7 9 11 ``` **输出**:1 **解释**:相邻元素差值均为 2,无法构成连号。 - **输入 3** ``` 7 3 4 5 4 5 6 7 ``` **输出**:4 **解释**:最长连号是 `4,5,6,7`,长度为 4。 ### 关键点 - **时间复杂度**:$O(n)$,只需一次遍历。 - **空间复杂度**:$O(n)$,用于存储输入序列。 - **边界处理**:当 $n=1$ 时,直接输出 1。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Z1Jxxx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值