题目链接
题目描述
给定一个长度为 的整数数组
。一个数组被称为“稳定”的,当且仅当对于数组中任意相邻的两个元素
和
,都满足
。
任务是求出给定数组 的最长稳定连续子数组的长度。
解题思路
这是一个求解满足特定局部性质的最长连续子数组的问题。我们可以通过一次线性扫描来解决,这种方法通常也被看作是一种简单的动态规划。
我们的核心思路是,在遍历数组的同时,维护当前以第 个元素结尾的最长稳定子数组的长度。
算法步骤如下:
-
初始化:
,用于记录全局的最长稳定子数组长度。任何单个元素的子数组都是稳定的,所以长度至少为 1(除非数组为空)。
,用于记录以当前元素结尾的稳定子数组的长度。
-
遍历数组:
- 从数组的第二个元素(下标为 1)开始,遍历到末尾。
- 在每一步,我们比较当前元素
和它前一个元素
。
- 如果
:这意味着稳定性质得以延续。当前元素
可以接在以上一个元素结尾的稳定子数组后面,形成一个更长的稳定子数组。因此,我们将
加 1。
- 如果
:这意味着稳定性质被破坏。一个新的稳定子数组必须从当前元素
开始。因此,我们将
重置为 1。
-
更新全局最长长度:
- 在每次更新(或重置)
之后,我们都需要用它来更新全局的
:
。
- 在每次更新(或重置)
-
处理边界情况:
- 如果输入的数组长度
为 0,最长长度应为 0。
- 如果
,最长长度至少为 1。我们的初始化已经覆盖了这一点。
- 如果输入的数组长度
遍历结束后, 中存储的就是最终的答案。
代码
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
int main() {
int n;
cin >> n;
if (n == 0) {
cout << 0 << endl;
return 0;
}
vector<int> a(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
int max_len = 1;
int current_len = 1;
for (int i = 1; i < n; ++i) {
if (abs(a[i] - a[i - 1]) <= 1) {
current_len++;
} else {
current_len = 1;
}
max_len = max(max_len, current_len);
}
cout << max_len << endl;
return 0;
}
import java.util.Scanner;
import java.lang.Math;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
if (n == 0) {
System.out.println(0);
return;
}
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
}
int maxLen = 1;
int currentLen = 1;
for (int i = 1; i < n; i++) {
if (Math.abs(a[i] - a[i - 1]) <= 1) {
currentLen++;
} else {
currentLen = 1;
}
maxLen = Math.max(maxLen, currentLen);
}
System.out.println(maxLen);
}
}
n = int(input())
if n == 0:
print(0)
else:
a = list(map(int, input().split()))
max_len = 1
current_len = 1
for i in range(1, n):
if abs(a[i] - a[i - 1]) <= 1:
current_len += 1
else:
current_len = 1
max_len = max(max_len, current_len)
print(max_len)
算法及复杂度
- 算法:线性扫描(或简单动态规划)。
- 时间复杂度:
,因为我们只对数组进行了一次遍历。
- 空间复杂度:
,主要用于存储输入的数组。