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

148 阅读1分钟

1027. 最长等差数列

难度:中等

时间:2024/04/21


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

解题思路:

dp[i][d] 表示以数组下标 i 处的元素结尾、公差为 d 的等差数列的最大长度。

动态规划思路:以每个元素作为等差数列终点,计算出该数列长度,选择出最大值返回即可。
在每个位置上,以字典结构保存该位置元素与前面每个位置上元素的差值,与对应该差值的数列长度。
class Solution:
    def longestArithSeqLength(self, nums: List[int]) -> int:
        minv, maxv = min(nums), max(nums)
        diff = maxv - minv
        ans = 1
​
        for d in range(-diff, diff + 1):
            f = dict()
            for num in nums:
                if (prev := num - d) in f:
                    f[num] = max(f.get(num, 0), f[prev] + 1)
                    ans = max(ans, f[num])
                f[num] = max(f.get(num, 0), 1)
        
        return ans
​
class Solution {
public:
    //  ---
    // 3 6 9 12
    // 1 2 3 4
    // dp[i][j] = {}
    // 动态规划,二维,注意,一维是存不了前向状态的
    // 为什么是二维而不是一维:一维dp递推时,前向的 N 可能是不通数列中,不能定唯一数列
    // 只有二维,能拿到差值信息
    
    int longestArithSeqLength(vector<int>& nums) {
        int len = nums.size();
        int res = 0;
        vector<vector<int>> dp(len,vector<int>(len,2));
        unordered_map<int,int> hash;
        for(int i=0;i<len;i++){
            for(int j=i+1; j<len; j++){
                int diff = nums[j] - nums[i];
                int p_v = nums[i]- diff;
                if(!hash.count(p_v)) continue;
                
                dp[i][j] = max(dp[i][j], dp[hash[p_v]][i]+1);
                res = max(res,dp[i][j]);
            }
            hash[nums[i]] = i;
            for(int j=0;j<len;j++){
                // printf("%d\t",dp[i][j]);
            }
            // printf("\r\n");
        }
        return max(res,2);
    }
};