自学内容网 自学内容网

每日一练:最长等差数列

1027. 最长等差数列 - 力扣(LeetCode)

题目要求:

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

解法-1 动态规划 O(N^2):

        这个题需要创建一个二维dp表,因为 nums[i] 可能与它之前的任何数字构成等差数列,所以用dp[i][j]保存以nums[j]、nums[i]为结尾的最长等差数列的长度;

        除此之外,还需要一个哈希表存放nums中的值的下标,否则直接遍历dp表时会超时;

        注意:

        因为nums的长度最小是3,所以最短的等差数列的长度肯定是2;

        因为nums中可能有重复元素,所以哈希表的值必须是一个数组,存储这个键的所有下标;

        找到符合条件的倒数第三个元素后,还需要这个元素的下标小于倒数第二个元素才行。

class Solution {
public:
    int longestArithSeqLength(vector<int>& nums) {
        int n = nums.size();

        unordered_map<int, vector<int>> hash;
        for (int i = 0; i < n; i++)
            hash[nums[i]].push_back(i);

        vector<vector<int>> dp(n);
        for (int i = 0; i < n; i++)
            dp[i].resize(i, 2);

        int ret = 2;
        for (int i = 2; i < n; i++) {
            for (int j = 1; j < i; j++) {
                int a = nums[j] - (nums[i] - nums[j]);
                if (hash.count(a)) // 能找到
                {
                    for(const int& v : hash[a])
                    {
                        if(v < j)
                            dp[i][j] = max(dp[i][j],dp[j][v]+1);
                    }
                }
                ret = max(dp[i][j], ret);
            }
        }

        return ret;
    }
};


原文地址:https://blog.csdn.net/2303_78095330/article/details/142768960

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!