题目:

1027. 最长等差数列
给你一个整数数组 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 <= 1000
0 <= nums[i] <= 500

动态规划:

思路 :
1. 定义DP数组
dp[i][d]:表示第i个数,与前面的数以差为d时,能构成的最长等差数列长度。
可以得到状态转移方程:dp[i][d] = max(dp[i][d],dp[j][d]+1),其中0<=j<i。
2. 元素差d的表示
由于数组元素大小为0<=nums[i]<=500,所以数组中 两元素差的范围为-500<= d<=500.
因此,可以使用d+500将差映射到[0,1000]方便我们定义dp数组。

  • 时间复杂度:O(n^{2})
  • 空间复杂度:O(n*d)
class Solution {
public int longestArithSeqLength(int[] nums) {
int len = nums.length;
if(len == 0) return 0;
int res = 0;
int[][]dp = new int[len][1001];
for(int i = 0; i < len;i++){
for(int j = 0; j < i;j++){
// nums[i]与其前面所有的数做差
int d = nums[i] - nums[j] + 500;
dp[i][d] = Math.max(dp[i][d],dp[j][d] + 1);
res = Math.max(res,dp[i][d]);
}
}
//初始化时 int[][] dp = new int[n][1010];元素默认值为 0,没有把等差子序列首元素算入其中。因此返回res+1.
//若刚开始全初始化为 1,后面直接返回ans
return res + 1;
}
}