难度 medium
给定一个整数数组 A,返回 A 中最长等差子序列的长度。
回想一下,A 的子序列是列表 A[i_1], A[i_2], ..., A[i_k] 其中 0 <= i_1 < i_2 < ... < i_k <= A.length - 1。并且如果 B[i+1] - B[i]( 0 <= i < B.length - 1) 的值都相同,那么序列 B 是等差的。
示例 1:
输入:[3,6,9,12]
输出:4
解释:
整个数组是公差为 3 的等差数列。
示例 2:
输入:[9,4,7,2,10]
输出:3
解释:
最长的等差子序列是 [4,7,10]。
示例 3:
输入:[20,1,15,3,10,5,8]
输出:4
解释:
最长的等差子序列是 [20,15,10,5]。
提示:
2 <= A.length <= 2000
0 <= A[i] <= 10000
解题思路:这道题目我用了接近一个小时还是没有解决,好菜,用来一个很笨的方法,结果超时了,然后参考了题解写出来的,这道题目用的是动态规划,动态规划还是容易跪,一定要把这东西记下来,不然这个情况到了秋招该怎么办。说回正题,这道题用的是等差数列,等差数列有一个重要的性质就是对于一个等差数列[nums[i], nums[j], nums[k]],有nums[j]2 = nums[i]+nums[k],因此我们就是利用了这个性质。用一个二维数组dp[i][j]表示以下标i,j对应的两个数字为结尾的等差数列,那么如果它存在前一个数,那前一个数就是nums[i]2-nums[j],于是我们用一个哈希map来保存数值和下标的对应关系,如果map中存在这个值,就更新动态规划方程,即dp[i][j] = dp[map.get(nums[i]*2-nums[j])][i]+1,否则说明这前一个数不存在,也就是以dp[i][j]结尾的等差数列最长就是nums[i]和nums[j]组成的数组,其长度为2,于是将dp[i][j]赋为2即可。我们还需要一个res来记录dp[i][j]的最大值,动态更新最后返回即可。
代码 t90 s70 java
class Solution {
public int longestArithSeqLength(int[] nums) {
HashMap<Integer,Integer> map = new HashMap<>();
int n = nums.length, res = Integer.MIN_VALUE;
int[][] dp = new int[n][n];
for(int i=0; i<n-1; i++){
for(int j=i+1; j<n; j++){
int t = nums[i] * 2 - nums[j];
if(map.containsKey(t)) dp[i][j] = dp[map.get(t)][i] + 1;
else dp[i][j] = 2;
res = Math.max(res, dp[i][j]);
}
map.put(nums[i], i);
}
return res;
}
}