LeetCode 1218. Longest Arithmetic Subsequence of Given Difference
2020-05-26 09:03:12 # leetcode

Problem

LeetCode 1218. Longest Arithmetic Subsequence of Given Difference

1. 题目简述

给出一个整形数组arr和一个整形数difference,找出arr所有子序列中以difference为间隔的最大长度。例如:

Examples:

Example 1:
Input: arr = [1,2,3,4], difference = 1
Output: 4
Explanation: The longest arithmetic subsequence is [1,2,3,4].

Example 2:
Input: arr = [1,3,5,7], difference = 1
Output: 1
Explanation: The longest arithmetic subsequence is any single element.

Example 3:
Input: arr = [1,5,7,8,5,3,4,2,1], difference = -2
Output: 4
Explanation: The longest arithmetic subsequence is [7,5,3,1].

Constraints:

1 <= arr.length <= 10^5
-10^4 <= arr[i], difference <= 10^4

2. 算法思路

Dynamic Programming

首先我们看一下给出的输入大小,基本上确定了不能使用暴力搜索,最多支持O(nlogn)级别的复杂度。所以我们判断使用动态规划来节约时间。

我们来看一下题目,要求找子序列,且difference确定,base case我们设定为长度为1的single element,maxLength就是1。然后对于第n个数,我们需要找到从第1个数到第 $ n - 1 $ 个数存不存在num[n] - difference,如果不存在,则说明以当前数字为结尾的最长子序列长度为1,也就是本身;如果存在,则为dp[n - difference] + 1,视情况更新maxLength。

对于判断是否存在num[n] - difference,有一个最好用的数据结构就是hashmap,key为数字,value为最后一次出现的index,对于重复的数,后出现的那个一定是包含先出现的情况。

dp[n] = dp[n - difference] + 1 (如果n - difference出现过)
dp[n] = 1 (如果n - difference没出现过)

3. 解法

Dynamic Programming bottom-up:数组最长为10^5,则dp数组长度为100001.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

class Solution {
public int longestSubsequence(int[] arr, int difference) {
int[] dp = new int[100000];
// key是数值,value是last index
Map<Integer, Integer> dict = new HashMap();
int longest = 1;

for (int i = 0; i < arr.length; i++) {
int targetIndex = dict.getOrDefault(arr[i] - difference, -1);
dict.put(arr[i], i);
if (targetIndex == -1) {
dp[i] = 1;
continue;
} else {
dp[i] = dp[targetIndex] + 1;
longest = Math.max(longest, dp[i]);
}
}

return longest;
}
}