1218. 最长定差子序列
题目描述
给你一个整数数组 arr 和一个整数 difference,请你找出并返回 arr 中最长等差子序列的长度,该子序列中相邻元素之间的差等于 difference 。
子序列 是指在不改变其余元素顺序的情况下,通过删除一些元素或不删除任何元素而从 arr 派生出来的序列。
提示:
- 1 < = a r r . l e n g t h < = 1 0 5 1 <= arr.length <= 10^5 1<=arr.length<=105
- − 1 0 4 < = a r r [ i ] , d i f f e r e n c e < = 1 0 4 -10^4 <= arr[i], difference <= 10^4 −104<=arr[i],difference<=104
my dp code tle
一开始仿照 300. 最长递增子序列 写法,使用 2 层 for 的 dp。
但是但是,由于本题
1
<
=
a
r
r
.
l
e
n
g
t
h
<
=
1
0
5
1 <= arr.length <= 10^5
1<=arr.length<=105,所以 2 层 for 就 tle
超时了。
// tle code
class Solution {
public int longestSubsequence(int[] arr, int difference) {
int n = arr.length;
int[] dp = new int[n]; // dp[i]表示[0,i]内最长定差子序列长度
int max = 0;
for (int i = 1; i < n; i++) {
for (int j = 0; j < i; j++) {
// 2、递推公式
if (arr[i] - arr[j] == difference) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
max = Math.max(max, dp[i]);
}
}
// 打印dp
System.out.println(Arrays.toString(dp));
return max + 1;
}
}
- 时间复杂度: O ( n 2 ) O(n^2) O(n2)
- 空间复杂度: O ( n ) O(n) O(n)
数组 + dp
由于题目中说了 − 1 0 4 < = a r r [ i ] , d i f f e r e n c e < = 1 0 4 -10^4 <= arr[i], difference <= 10^4 −104<=arr[i],difference<=104,所以可以开一个 1 0 4 10^4 104 的数组。
- 状态转移方程:
dp[i + 20000] = Math.max(dp[i + 20000], dp[i + 20000 - difference] + 1);
最终,取所有 d p [ i ] dp[i] dp[i] 的 max,即可。
class Solution {
public int longestSubsequence(int[] arr, int difference) {
int n = 40000;
int[] dp = new int[n]; // dp[i]表示arr中以i元素结尾最长定差子序列长度
int max = 0;
for (int i : arr) {
dp[i + 20000] = Math.max(dp[i + 20000], dp[i + 20000 - difference] + 1);
max = Math.max(max, dp[i + 20000]);
}
// 打印dp
// System.out.println(Arrays.toString(dp));
return max;
}
}
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( 1 0 4 ) O(10^4) O(104)
map + dp
由于本题数据量还是有点大,如何所给数组 arr 过于稀疏是,开 1 0 4 10^4 104 的数组不免浪费空间。
所以,可以采用 map 来充当 dp 数组是更好的选择。
class Solution {
public int longestSubsequence(int[] arr, int difference) {
int n = 40000;
Map<Integer, Integer> dp = new HashMap<>(); // dp[i]表示arr中以i元素结尾最长定差子序列长度
int max = 0;
for (int i : arr) {
dp.put(i, dp.getOrDefault(i - difference, 0) + 1);
max = Math.max(max, dp.get(i));
}
// 打印dp
// System.out.println(Arrays.toString(dp));
return max;
}
}
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( n ) O(n) O(n)