一、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;
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,