给定一个整数数组,返回其中最长的等差子序列的长度。子序列是原数组中任意几个元素按原顺序组成的新序列,不要求连续。
Example 1:
Input: nums = [3,6,9,12]
Output: 4
Explanation: The whole array is an arithmetic sequence with steps of length = 3.
🔍 解题思路:
用 动态规划 的思想解决这个问题,核心是维护以每个元素结尾的、不同差值的最长等差序列长度。
🔑 关键点:
-
用一个数组
dp[i]表示以array[i]结尾的所有差值对应的最长等差序列。 -
dp[i]是一个Map<Integer, Integer>,键是差值diff,值是以这个差值结尾的最长子序列长度。 -
对于每个元素
array[i],往前找所有j<i的元素,计算差值diff = array[i] - array[j]:- 如果
dp[j]中没有这个差值,说明当前是新开始的长度为 2 的序列。 - 否则,就可以接在
dp[j].get(diff)的基础上,长度 +1。
- 如果
📌 代码解释
public class LongestArithSequenceLength {
public int longestArithSequenceLength(int[] array) {
if (array == null || array.length < 2) return 0;
int globalMax = 0;
Map<Integer, Integer>[] dp = new Map[array.length];
for (int i = 0; i < array.length; i++) {
dp[i] = new HashMap<>();
for (int j = 0; j < i; j++) {
int diff = array[i] - array[j];
// 如果之前没有这种差值的序列,从2开始
int len = dp[j].getOrDefault(diff, 1) + 1;
dp[i].put(diff, len);
globalMax = Math.max(globalMax, len);
}
}
return globalMax;
}
}
⏱️ 时间复杂度:
- 外层两层循环:
O(n^2) - 内部的
HashMap操作是O(1)平均时间
✅ 所以总时间复杂度是:O(n²)
🧠 总结:
这道题考察的是动态规划中对状态定义和存储结构的掌握:
- 如何定义状态 dp[i]
- 如何表示差值 diff
- 如何记录历史并延长已有序列
它是典型的“状态依赖之前所有结果”类型问题,非常适合巩固对动态规划的理解。