LeetCode-1027-最长等差子数列

248 阅读1分钟

题目描述

给定一个整数数组 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

思路分析

在该题中单个状态为:第i个数差为diff时的最长序列的值。

状态转移方程为:

第i个数,差为diff时的最长序列值 = max(A, B)

A: 与数i一起构成差为diff的数j,且当数j差为diff的最长序列值+1

B: 第i个数,差为diff时的最长序列值 // 因为与i构成差值diff的不止j也有可能是k等等

AC代码

var longestArithSeqLength = function(A) {
    let maxLen = 0
    let dp = [{}]
    let size = A.length
    for(let i = 1; i < size; i++) {
        !dp[i] && ( dp[i] = {} )

        for(let j = 0; j < i; j++) {
            let diff = A[i] - A[j] 

            !dp[i][diff] && ( dp[i][diff] = 2 )

            if(dp[j][diff] > 0) {
                dp[i][diff] = Math.max(dp[j][diff] + 1, dp[i][diff])
            }

            maxLen = Math.max(dp[i][diff], maxLen)
        }
    }
    return maxLen
};

总结

动态规划使用条件:

1.题目有个阈值(最大、小、长、短...之类的)
2.前一个最X状态可以构成后一个最X状态