一、Problem
Given an integer array nums and an integer k, return the maximum sum of a non-empty subsequence of that array such that for every two consecutive integers in the subsequence, nums[i] and nums[j], where i < j, the condition j - i <= k is satisfied.
A subsequence of an array is obtained by deleting some number of elements (can be zero) from the array, leaving the remaining elements in their original order.
Input: nums = [10,2,-10,5,20], k = 2
Output: 37
Explanation: The subsequence is [10, 2, 5, 20].
Constraints:
二、Solution
方法一:dp(超时)
- 定义状态:
- 表示以 结尾的最大子序列和
- 思考初始化:
- 表示最短的子序列和为自己
- 思考状态转移方程:
- ,MSS 要么是以 i 结尾,要么是以区间 中任意一个数结尾,且选上
- 思考输出:
预期是超时的,但还是提交了一发…
class Solution {
public int constrainedSubsetSum(int[] A, int k) {
int n = A.length, dp[] = new int[n+5], max = A[0];
for (int i = 0; i < n; i++)
dp[i] = A[i];
for (int i = 1; i < n; i++)
for (int j = Math.max(0, i-k); j < i; j++) {
dp[i] = Math.max(dp[i], dp[j] + A[i]);
max = Math.max(max, dp[i]);
}
return max;
}
}
复杂度分析
- 时间复杂度:,
- 空间复杂度:,
方法二:单调队列优化
比赛时我还不知道单调队列这个事,要不让可以轻松拿下。由上可得 dp 方程为:
中间求区间 最大值这一步可用单调队列优化掉…
class Solution {
public int constrainedSubsetSum(int[] A, int k) {
int n = A.length, dp[] = new int[n+5], max = A[0];
for (int i = 0; i < n; i++)
dp[i] = A[i];
int hh = 0, tt = 0, q[] = new int[(int) 1e5+5];
q[++tt] = 0;
for (int i = 1; i < n; i++) {
while (hh <= tt && q[hh] < i-k)
hh++;
dp[i] = Math.max(dp[i], dp[q[hh]] + A[i]);
max = Math.max(max, dp[i]);
while (hh <= tt && dp[q[tt]] < dp[i])
tt--;
q[++tt] = i;
}
return max;
}
}
复杂度分析
- 时间复杂度:,
- 空间复杂度:,