lc.1425.带限制的子序列和
给你一个整数数组 nums 和一个整数 k ,请你返回 非空 子序列元素和的最大值,子序列需要满足:子序列中每两个 相邻 的整数 nums[i] 和 nums[j] ,它们在原数组中的下标 i 和 j 满足 i < j 且 j - i <= k 。
数组的子序列定义为:将数组中的若干个数字删除(可以删除 0 个数字),剩下的数字按照原本的顺序排布。
示例 1:
1
2
3
|
输入:nums = [10,2,-10,5,20], k = 2
输出:37
解释:子序列为 [10, 2, 5, 20] 。
|
示例 2:
1
2
3
|
输入:nums = [-1,-2,-3], k = 1
输出:-1
解释:子序列必须是非空的,所以我们选择最大的数字。
|
示例 3:
1
2
3
|
输入:nums = [10,-2,-10,-5,20], k = 2
输出:23
解释:子序列为 [10, -2, -5, 20] 。
|
提示:
$1 <= k <= nums.length <= 10^5$
$-10^4 <= nums[i] <= 10^4$
解题代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
//dp[i] = max(dp[j],0) + nums[j] (i-j<=k) and j<i
class Solution {
public:
int constrainedSubsetSum(vector<int>& nums, int k) {
int n = nums.size();
if (n<=0) return 0;
vector<int> dp(n+1);
deque<int> q;
q.push_back(0);
dp[0] = nums[0];
int res = nums[0];
for (int i=1;i<n;i++) {
while(q.size() && q.front() < i- k) q.pop_front();
// 单调栈顶部就是最大d,直接取出计算即可
// 坑:排除负数,此时宁愿只取nums[i]
dp[i] = max(0,dp[q.front()]) + nums[i];
res = max(res,dp[i]);
/// 构建单调栈, 弹出队列里比自己小
while(q.size() && dp[i] > dp[q.back()]) q.pop_back();
q.push_back(i);
}
return res;
}
};
|