美文网首页动态规划动态规划
【DP】1027. Longest Arithmetic Seq

【DP】1027. Longest Arithmetic Seq

作者: 牛奶芝麻 | 来源:发表于2019-04-30 14:31 被阅读0次

    问题描述:

    Given an array A of integers, return the length of the longest arithmetic subsequence in A.

    Recall that a subsequence of A is a list A[i_1], A[i_2], ..., A[i_k] with 0 <= i_1 < i_2 < ... < i_k <= A.length - 1, and that a sequence B is arithmetic if B[i+1] - B[i] are all the same value (for 0 <= i < B.length - 1).

    Example 1:
    Input: [3,6,9,12]
    Output: 4
    Explanation: 
    The whole array is an arithmetic sequence with steps of length = 3.
    
    Example 2:
    Input: [9,4,7,2,10]
    Output: 3
    Explanation: 
    The longest arithmetic subsequence is [4,7,10].
    
    Example 3:
    Input: [20,1,15,3,10,5,8]
    Output: 4
    Explanation: 
    The longest arithmetic subsequence is [20,15,10,5].
    
    Note:
    2 <= A.length <= 2000
    0 <= A[i] <= 10000
    

    解题思路:

    这是一道求最长等差子序列的动态规划题目。问题的关键在于记录每一个元素与之前所有元素的差值次数。
    [9,4,7,2,10] 为例,对于数字7,前面的数中,9与它的差值为2,4与它的差值为-3,因此可以考虑用dict {差值: 次数}来记录7。对于数字10,当遍历10前面的数字时,遍历到7,差值是-3,因为-3在7的位置出现过,因此在10的位置处,差值为-3的次数就为2。

    因此,我们可以对列表中的每一个数建立一个字典,数据结构为 dp = [dict() for _ in A](注意不要写成 dp = [dict()] * len(A),因为这样在每次修改 dp[i] 时,其他的dict()会同时修改,即这样的初始化字典数组的方法是传引用式的)。

    对于 dp[i][j] = k,表示以第 i 个数结尾的子序列,差为 j 时的最长子序列长度为 k。如上述例子,记录以7为结尾的子序列的差值和次数,7对应的字典应该是 {2: 1, -3:1},即 dp[2][2] = 1, dp[2][-3] = 1

    对任何差值 x,dp[i][x] = 1 为初始状态。每次循环枚举 j < i,计算 x = A[j] − A[i],如果差值 x 在 dp[j] 元素中出现过,则转移方程为 dp[i][x] = dp[j][x] + 1

    最后,返回 dp 中所有 N 个字典中的次数的最大值,+1 就是最后的结果(因为求的是等差子序列的长度,因此结果等于最大差值次数加1)。

    时间复杂度为 O(n^2),空间复杂度也为 O(n^2)。

    Python3 实现:

    class Solution:
        def longestArithSeqLength(self, A):
            dp = [dict() for _ in A]
            maxl = 0
            for i in range(1, len(A)):
                for j in range(0, i):
                    sub = A[j] - A[i]
                    if sub in dp[j].keys():
                        dp[i][sub] = dp[j][sub] + 1
                    else:
                        dp[i][sub] = 1
                    maxl = max(maxl, dp[i][sub])
            return maxl + 1
    
    print(Solution().longestArithSeqLength([9,4,7,2,10]))  # 3
    print(Solution().longestArithSeqLength([83,20,17,43,52,78])) # 2
    

    相关文章

      网友评论

        本文标题:【DP】1027. Longest Arithmetic Seq

        本文链接:https://www.haomeiwen.com/subject/wnxvnqtx.html