1027. 最长等差数列
1027. 最长等差数列
🟠 🔖 数组 哈希表 二分查找 动态规划 🔗 力扣 LeetCode
题目
Given an array nums of integers, return the length of the longest arithmetic subsequence in nums.
Note that:
- A subsequence is an array that can be derived from another array by deleting some or no elements without changing the order of the remaining elements.
- A sequence
seqis arithmetic ifseq[i + 1] - seq[i]are all the same value (for0 <= i < seq.length - 1).
Example 1:
Input: nums = [3,6,9,12]
Output: 4
Explanation: The whole array is an arithmetic sequence with steps of length = 3.
Example 2:
Input: nums = [9,4,7,2,10]
Output: 3
Explanation: The longest arithmetic subsequence is [4,7,10].
Example 3:
Input: nums = [20,1,15,3,10,5,8]
Output: 4
Explanation: The longest arithmetic subsequence is [20,15,10,5].
Constraints:
2 <= nums.length <= 10000 <= nums[i] <= 500
题目大意
给你一个整数数组 nums,返回 nums 中最长等差子序列的长度 。
回想一下,nums 的子序列是一个列表 nums[i1], nums[i2], ..., nums[ik] ,且 0 <= i1 < i2 < ... < ik <= nums.length - 1。并且如果 seq[i+1] - seq[i]( 0 <= i < seq.length - 1) 的值都相同,那么序列 seq 是等差的。
示例 1:
输入: nums = [3,6,9,12]
输出: 4
解释:
整个数组是公差为 3 的等差数列。
示例 2:
输入: nums = [9,4,7,2,10]
输出: 3
解释:
最长的等差子序列是 [4,7,10]。
示例 3:
输入: nums = [20,1,15,3,10,5,8]
输出: 4
解释:
最长的等差子序列是 [20,15,10,5]。
提示:
2 <= nums.length <= 10000 <= nums[i] <= 500
解题思路
定义状态
dp[i][diff]dp[i][diff]代表 以nums[i]结尾,公差为diff的最长等差子序列的长度。- 我们用 哈希表
Map代替二维数组 来存储(i, diff) -> 长度关系,减少不必要的存储。
状态转移方程
- 枚举
j < i,计算diff = nums[i] - nums[j]:- 若
dp[j][diff]存在,则dp[i][diff] = dp[j][diff] + 1 - 否则,
dp[i][diff] = 2(默认至少包含nums[j]和nums[i])
- 若
- 枚举
优化
- 由于
dp[i][diff]只依赖于dp[j][diff],我们 直接用Map存储(索引 i, 公差 diff) -> 最长长度。 - 这样可以 避免
O(n^2)级别的二维数组存储开销,提升空间效率。
- 由于
复杂度分析
- 时间复杂度:
O(n^2),需要两层循环遍历所有(i, j)组合。 - 空间复杂度:
O(n * d),其中d是nums[i] - nums[j]的取值范围,通常小于O(n^2),相比dp[i][diff]方式更节省空间。
代码
/**
* @param {number[]} nums
* @return {number}
*/
var longestArithSeqLength = function (nums) {
const n = nums.length;
if (n <= 2) return n;
let maxLen = 2;
const dp = new Map(); // 只存储实际的 (索引, 差值) 组合
for (let i = 0; i < n; i++) {
for (let j = 0; j < i; j++) {
const diff = nums[i] - nums[j];
const key = `${i},${diff}`; // 组合索引和公差
dp.set(key, (dp.get(`${j},${diff}`) || 1) + 1);
maxLen = Math.max(maxLen, dp.get(key));
}
}
return maxLen;
};
相关题目
| 题号 | 标题 | 题解 | 标签 | 难度 | 力扣 |
|---|---|---|---|---|---|
| 2453 | 摧毁一系列目标 | 数组 哈希表 计数 | 🟠 | 🀄️ 🔗 |
