[LeetCode] 1027. Longest Arithmetic Subsequence 最长的等差数列


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: A = [3,6,9,12]
Output: 4
Explanation:
The whole array is an arithmetic sequence with steps of length = 3.

Example 2:

Input: A = [9,4,7,2,10]
Output: 3
Explanation:
The longest arithmetic subsequence is [4,7,10].

Example 3:

Input: A = [20,1,15,3,10,5,8]
Output: 4
Explanation:
The longest arithmetic subsequence is [20,15,10,5].

Constraints:

  • 2 <= A.length <= 1000
  • 0 <= A[i] <= 500

这道题给了一个数组,让找最长的等差数列的长度,暴力搜索的时间复杂度太大,这里就不考虑了。像这种玩数组,求极值的题,刷题老司机们应该很容易就反应出应该用动态规划 Dynamic Programming 来做,首先来考虑如何定义 DP 数组,最直接的就是用一个一维数组,其中 dp[i] 表示区间 [0, i] 中的最长等差数列的长度,但是这样定义的话,很难找出状态转移方程。因为有些隐藏信息被我们忽略了,就是等差数列的相等的差值,不同的等差数列的差值可以是不同的,所以不包括这个信息的话将很难更新 dp 值。所以这里就需要一个二维数组,dp[i][j] 表示在区间 [0, i] 中的差值为j的最长等差数列的长度减1,这里减1是因为起始的数字并没有被算进去,不过不要紧,最后再加回来就行了。还有一个需要注意的地方,由于等差数列的差值有可能是负数,而数组的下标不能是负数,所以需要处理一下,题目中限定了数组中的数字范围为0到 500 之间,所以差值的范围就是 -500 到 500 之间,可以给差值加上个 1000,这样差值范围就是 500 到 1500 了,二维 dp 数组的大小可以初始化为 nx2000。更新 dp 值的时候,先遍历一遍数组,对于每个遍历到的数字,再遍历一遍前面的所有数字,算出差值 diff,再加上 1000,然后此时的 dp[i][diff] 可以赋值为 dp[j][diff]+1,然后用这个新的 dp 值来更新结果 res,最后别忘了 res 加1后返回,参见代码如下:


class Solution {
public:
    int longestArithSeqLength(vector<int>& A) {
        int res = 0, n = A.size();
        vector<vector<int>> dp(n, vector<int>(2000));
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < i; ++j) {
                int diff = A[i] - A[j] + 1000;
                dp[i][diff] = dp[j][diff] + 1;
                res = max(res, dp[i][diff]);
            }
        }
        return res + 1;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1027


参考资料:

https://leetcode.com/problems/longest-arithmetic-subsequence/

https://leetcode.com/problems/longest-arithmetic-subsequence/discuss/274611/JavaC%2B%2BPython-DP


LeetCode All in One 题目讲解汇总(持续更新中...)

posted @ 2021-02-13 11:10  Grandyang  阅读(1588)  评论(1编辑  收藏  举报
Fork me on GitHub