按照最长递增子序列的思路dp
class Solution {
public int longestSubsequence(int[] arr, int difference) {
// dp[i]: arr[0~i] 中且以i结尾的最长定差子序列
int dp[] = new int[arr.length];
dp[0] = 1;
int res = 1;
for (int i = 1; i < arr.length; i++) {
dp[i] = 1;
for (int j = i - 1; j >= 0; j--) {
if (arr[i] - arr[j] == difference) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
res = Math.max(res, dp[i]);
}
return res;
}
}
超时
本题比最长递增子序列限制多,不必在内层for循环中一个个找, 目标很明确,比如差值是2, 当前arr[i] = 3, 那即找前面以1结尾的最长定差子序列的最大值即可(数组的值存在重复),可以优化掉内层for循环; 因为数组存在负数值, 用map记录arr[i]结尾的最长定差子序列长度(也可以将原数组都增加一个固定值,保证数组值都是正数, 改用数组记录)
优化内存for循环
class Solution {
public int longestSubsequence(int[] arr, int difference) {
Map<Integer, Integer> map = new HashMap<>();
map.put(arr[0], 1);
int res = 1;
for (int i = 1; i < arr.length; i++) {
int cur = map.getOrDefault(arr[i]-difference, 0) + 1;
if (cur > map.getOrDefault(arr[i], 0)) {
map.put(arr[i], cur);
res = Math.max(res, cur);
}
}
return res;
}
}
执行耗时:43 ms,击败了37.06% 的Java用户
内存消耗:54.3 MB,击败了67.01% 的Java用户
hash还是比较耗时,改为数组
class Solution {
public int longestSubsequence(int[] arr, int difference) {
// 都增加一个值,不影响结果; 保证arr[i] 和 arr[i]-difference都是正数
for (int i = 0; i < arr.length; i++) {
arr[i] += 20000;
}
// arr[i]: 1W~3W, difference:-1W~1W, arr[i]-difference: 0~4W
int[] dp = new int[40001];
dp[arr[0]] = 1;
int res = 1;
for (int i = 1; i < arr.length; i++) {
if (dp[arr[i]-difference] + 1 > dp[arr[i]]) {
dp[arr[i]] = dp[arr[i]-difference] + 1;
res = Math.max(res, dp[arr[i]]);
}
}
return res;
}
}
执行耗时:4 ms,击败了95.94% 的Java用户
内存消耗:47.3 MB,击败了93.40% 的Java用户