最长等差数列的长度(进阶版——允许公差为零且包含负数)
字数 1187 2025-11-03 08:34:44
最长等差数列的长度(进阶版——允许公差为零且包含负数)
题目描述:
给定一个整数数组 nums,返回数组中最长等差数列的子序列长度。等差数列至少包含3个元素,且公差可以是任意整数(包括零和负数)。例如,对于数组 [3, 6, 9, 12],最长等差数列是整个数组,长度为4。
解题过程:
-
问题分析:
我们需要找到最长的等差数列子序列(不一定连续)。与基础版不同,这里公差可以是零(所有相等元素)或负数,且数组可能包含正负整数。 -
动态规划状态定义:
定义 dp[i][d] 表示以第 i 个元素结尾、公差为 d 的最长等差数列长度。但由于 d 可能是任意整数,直接使用二维数组会占用过大空间。更高效的方法是用字典(哈希表)来存储状态:
- 令 dp[i] 是一个字典,键为公差 d,值为以 nums[i] 结尾、公差为 d 的等差数列长度。
- 状态转移方程:
对于每个 i(从 0 到 n-1),遍历所有 j(从 0 到 i-1):
- 计算公差 d = nums[i] - nums[j]。
- 如果 dp[j] 中存在公差 d 的键,说明 nums[j] 已经属于某个公差为 d 的等差数列,则我们可以将 nums[i] 接在这个数列后面:dp[i][d] = dp[j][d] + 1。
- 如果 dp[j] 中没有公差 d,说明从 nums[j] 到 nums[i] 可以形成一个长度为 2 的新等差数列:dp[i][d] = 2。
- 同时,更新全局最大值 max_len。
-
初始化:
每个元素本身可以视为长度为 1 的等差数列,但题目要求至少 3 个元素,因此初始时 max_len = 0(或 1,如果允许长度为 2,但题目要求至少 3)。实际上,我们只记录长度 ≥ 2 的序列,最终返回时如果 max_len < 3 则返回 0。 -
复杂度优化:
使用字典存储公差,空间复杂度 O(n²)(最坏情况),时间复杂度 O(n²)。由于数组长度可能较大,需注意哈希操作的开销。 -
示例演示:
以 nums = [1, 3, 5, 7, 9, 11] 为例:
- i=0: 无前驱,dp[0] = {}。
- i=1: 与 j=0 比较,d=2,dp[1][2] = 2。
- i=2: 与 j=0: d=4,dp[2][4]=2;与 j=1: d=2,dp[2][2] = dp[1][2] + 1 = 3。
- 继续处理,最终找到公差 2 的等差数列长度为 6。
- 边界情况:
- 数组长度小于 3 时直接返回 0。
- 所有元素相等时,公差 d=0,等差数列长度为 n。
- 包含负数时,公差可能为负,但计算时直接使用 nums[i] - nums[j] 即可,字典能处理负键。
通过以上步骤,即可高效求出最长等差数列长度。