不能直接用 std::max_element 找最长等差数列,因为它只能比较元素大小,无法判断子序列或子数组的公差一致性;连续情况可用双指针 O(n),非连续必须二维 DP+哈希优化 O(n²)。

为什么不能直接用 std::max_element 找最长等差数列
因为等差数列不是单个元素的属性,而是子序列(不一定是连续)或子数组(连续)的结构特征。std::max_element 只能比大小,无法判断公差一致性。常见误判是把“最长连续等差子数组”当成“最长(任意位置)等差子序列”,两者解法完全不同——前者可用双指针 O(n),后者必须动态规划 O(n²)。
连续等差子数组:用双指针维护当前公差
如果题目明确要求“连续”,比如数组 [1,3,5,7,2,4] 中最长连续等差段是 [1,3,5,7](长度 4,公差 2),那就不用 DP:
- 从索引 1 开始遍历,计算
diff = arr[i] - arr[i-1] - 用变量
curr_len记录当前连续段长度,max_len记全局最大值 - 若
arr[i] - arr[i-1] == diff,则curr_len++;否则重置curr_len = 2、更新diff - 注意边界:长度 ≤ 2 的数组直接返回原长
示例代码核心逻辑:
int longestArithSeqLength(vector<int>& arr) {
if (arr.size() <= 2) return arr.size();
int max_len = 2, curr_len = 2;
int diff = arr[1] - arr[0];
for (int i = 2; i < arr.size(); ++i) {
if (arr[i] - arr[i-1] == diff) {
curr_len++;
max_len = max(max_len, curr_len);
} else {
curr_len = 2;
diff = arr[i] - arr[i-1];
}
}
return max_len;
}
非连续等差子序列:必须用二维 DP + 哈希优化
LeetCode 1027 题型:在 [9,4,7,2,10] 中找最长等差子序列(答案是 [4,7,10] 或 [9,7,2],长度 3)。暴力枚举所有子序列是指数级,正确做法是:
- 定义
dp[i][diff]表示以arr[i]结尾、公差为diff的最长子序列长度 - 但
diff可能很大(如INT_MIN到INT_MAX),不能开二维数组,改用unordered_map<int, int>存每个下标对应的公差映射 - 对每个
i,遍历j从0到i-1,算diff = arr[i] - arr[j],然后dp[i][diff] = dp[j][diff] + 1(若dp[j][diff]不存在则为 2) - 时间复杂度 O(n²),空间 O(n²) —— 每个
i最多存 n 个不同公差
关键细节:diff 是 int 类型,但 C++ 中负数哈希无问题;不要用 map(log n 开销),坚持用 unordered_map。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
立即学习“C++免费学习笔记(深入)”;
容易被忽略的边界和性能坑
实际写的时候这几个点最常出错:
- 输入为空或只有 1 个元素时,直接返回
arr.size(),别进循环 - 公差为 0 的情况必须支持(如
[1,1,1,2,2],最长是 3 个 1),diff == 0不影响哈希键 - 用
vector<unordered_map<int, int>> dp(n)初始化,别写成dp[i].insert({diff, 2})而漏掉已有值——要写dp[i][diff] = max(dp[i][diff], dp[j][diff] + 1) - LeetCode 测试用例含大数组(n ≈ 1000),O(n³) 暴力必超时,DP 外层循环不能嵌套查找
真正卡住人的往往不是算法思路,而是 dp[j].count(diff) 判断写错位置,或者把 dp[i][diff] 初始化成 1 而不是 2。

















