【每日一题】最长等差数列

1027. 最长等差数列

关键词:动态规划、线性dp

题目来源:1027. 最长等差数列 - 力扣(Leetcode)

题目描述

 T动态规划
 T线性dp

给你一个整数数组 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 是等差的。

输入:nums = [3,6,9,12]
输出:4
解释: 
整个数组是公差为 3 的等差数列。
输入:nums = [9,4,7,2,10]
输出:3
解释:
最长的等差子序列是 [4,7,10]。
输入:nums = [20,1,15,3,10,5,8]
输出:4
解释:
最长的等差子序列是 [20,15,10,5]。
数据范围
2 <= nums.length <= 1000
0 <= nums[i] <= 500

问题分析

本题与最长递增子序列几乎相同。回顾最长递增子序列的做法:枚举a[i],以a[i]结尾的最长递增子序列等于max(f[j]),其中a[j]<a[i]且j<i。本题同样是求最长“递增子序列”,不同的是,本题的“递增”有可能为负,且每次“递增的量必须相同”,于是,需要增加一维,用于记录每次递增的量,也即有如下定义:

f(i, d) = 以a[i]结尾的,“增量”为d的最长序列的长度,于是有:f(i, d) = f(j, d) + 1,其中d=a[i]-a[j]。由于d可能为负,当不会小于﹣500,可以统一+500。

时间复杂度:O(n^2)

空间复杂度:O(n^2)

代码实现

int longestArithSeqLength(vector<int> &nums) {
    const int N = 500, M = (N << 1) + 5;
    int f[N][M] = {0}, n = nums.size(), maxLen = 0;
    for (int i = 1, d; i < n; i++) {
        for (int j = 0; j < i; j++) {
            d = nums[i] - nums[j] + N;
            f[i][d] = f[j][d] + 1;
            maxLen = max(f[i][d], maxLen);
        }
    }
    return maxLen+1;
}
posted @ 2023-04-22 10:42  字节幺零二四  阅读(51)  评论(0)    收藏  举报