1. 程式人生 > 實用技巧 >[LeetCode] 1027. Longest Arithmetic Subsequence

[LeetCode] 1027. Longest Arithmetic Subsequence

Given an arrayAof integers, return thelengthof the longest arithmetic subsequence inA.

Recall that asubsequenceofAis a listA[i_1], A[i_2], ..., A[i_k]with0 <= i_1 < i_2 < ... < i_k <= A.length - 1, and that a sequenceBisarithmeticifB[i+1] - B[i]are all the same value (for0 <= 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 題目總結