1218. 最长定差子序列
给你一个整数数组 arr 和一个整数 difference,请你找出并返回 arr 中最长等差子序列的长度,该子序列中相邻元素之间的差等于 difference 。
子序列 是指在不改变其余元素顺序的情况下,通过删除一些元素或不删除任何元素而从 arr 派生出来的序列。
题解
方法一:动态规划
因为子序列可以删减原序列的元素,所以不能简单的一次遍历。在这里求等差子序列的长度,在遍历过程中,当前序列的结果与前面序列的结果相关,我们可以使用动态规划方法。
但是,如果使用普通dp数组的方式存储,由于每一次都要找递归序列的前一个值,时间复杂度会达到O(n^2)。
class Solution {
public int longestSubsequence(int[] arr, int difference) {
int n = arr.length;
if(n <= 1) return n;
int maxLen = 1;
int[] dp = new int[n];
dp[0] = 1;
for(int i = 1; i < n; i++){
dp[i] = 1;
for(int j = 0; j < i; j++){
if(arr[i] - arr[j] == difference){
dp[i] = dp[j] + 1;
maxLen = Math.max(maxLen, dp[i]);
}
}
}
return maxLen;
}
}
这里其实我们只要找到当前值在递归序列的前一个值对应的子序列长度,再+1就好了,那么可以使用哈希表存储以arr[i]为结尾的最长等差子序列长度。
当遍历到arr[i]的时候,就去map中找 arr[i]-difference,
- 如果存在,arr[i]对应的子序列长度就为 map.get(arr[i]-difference) + 1;
- 如果不存在,arr[i]对应的子序列长度就为 1。
class Solution {
public int longestSubsequence(int[] arr, int difference) {
Map<Integer, Integer> map = new HashMap<>();
int maxLen = 1;
for(int x : arr){
int val = map.getOrDefault(x - difference, 0); // 如果不存在前序值就返回0
map.put(x, val + 1); // 将当前值对应的子序列长度存入map
maxLen = Math.max(maxLen, val + 1);
}
return maxLen;
}
}