题目描述
给定一个长度为 n 的整数数组 nums,请你找出最长的连续子数组 ,使得该子数组中任意相邻两个元素的差的绝对值恰好为 1。
返回这个最长连续子数组的长度。
注意:子数组是数组中连续的一段,不能排序或改变顺序。
输入描述
-
第一行:整数 n(1 ≤ n ≤ 10^5)
-
第二行:n 个整数,表示数组 nums(-10^9 ≤ numsi ≤ 10^9)
输出描述
- 输出一个整数,表示满足条件的最长连续子数组的长度
示例 1
text
输入:
5
1 2 3 5 6
输出:
3
解释:子数组 [1,2,3] 满足相邻差绝对值为1,长度为3。
示例 2
text
输入:
6
1 2 3 4 3 2
输出:
4
解释:子数组 [1,2,3,4] 长度为4,或 [4,3,2] 长度为3,最长是4。
示例 3
text
输入:
4
5 5 5 5
输出:
1
解释:任意相邻元素差为0,不满足绝对值为1,所以最长长度为1(单个元素视为满足)。
解法思路
核心思想:一次遍历(双指针 / 滑动窗口)
由于要求的是连续子数组,且条件只与相邻元素有关,我们可以用一次线性扫描解决:
-
维护一个变量
cur表示以当前位置结尾的最长满足条件的子数组长度。 -
遍历数组,对于每个位置 i(从1开始):
-
如果
|nums[i] - nums[i-1]| == 1,则cur += 1 -
否则,
cur = 1(重新开始) -
用
ans记录cur的最大值
-
时间复杂度 O(n),空间复杂度 O(1)。
为什么不需要滑动窗口?
因为条件只依赖于相邻两个元素,一旦某个相邻对不满足,前面的子数组就无法再延伸,直接重置即可。这类似于求最长连续递增子序列的简化版。
cpp
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
int main() {
int n;
cin >> n;
vector<long long> nums(n);
for (int i = 0; i < n; i++) cin >> nums[i];
int ans = 1, cur = 1;
for (int i = 1; i < n; i++) {
if (abs(nums[i] - nums[i-1]) == 1) {
cur++;
ans = max(ans, cur);
} else {
cur = 1;
}
}
cout << ans << endl;
return 0;
}