[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

最长等差数列。

题意是给一个整数数组,请你返回这个数组中最长的等差数列的长度。

思路是动态规划。这道题是300题那种类似LIS的题目的延伸,但是这道题的一个难点在于你不光是要找升序或者降序的子数组,统计长度,同时你需要保持这个子数组的等差的。所以这里我们需要一个二维数组来模拟动态规划的过程。这里我们动态规划 dp[i][j] 的定义是以 nums[i] 结尾,差值为 j 的最长的满足题意的子数组(有可能是升序也有可能是降序)。这里的等差因为有可能是升序有可能是降序所以等差的差有可能是正数也有可能是负数。这里我们做一个处理,注意题设给的数据范围是从0到500,所以最极端的等差有可能是从正500到负500所以我们DP数组的第二维的长度给1001。

还是跟300题类似的思路做两层循环,对于每一个 nums[i] ,我们去找 0 - i 范围内每两个数字之间的等差。我们对这个等差无条件 + 500,这样一些小于0的差值也就被存到了DP数组里面。对于 dp[i][diff] 而言,更新他的长度也跟300题类似。注意最后返回的是max + 1,因为每个数字自己可以自成一个等差数列。

时间O(n^2)

空间O(n^2)

Java实现

 1 class Solution {
 2     public int longestArithSeqLength(int[] nums) {
 3         int max = 0;
 4         int[][] dp = new int[nums.length + 1][1001];
 5         for (int i = 0; i < nums.length; i++) {
 6             for (int j = 0; j < i; j++) {
 7                 int temp = (nums[i] - nums[j]) + 500;
 8                 dp[i][temp] = dp[j][temp] + 1;
 9                 max = Math.max(max, dp[i][temp]);
10             }
11         }
12         return max + 1;
13     }
14 }

LIS类相关题目

LeetCode 题目总结

原文地址:https://www.cnblogs.com/cnoodle/p/13972338.html