带限制的子序列和
难度:
标签:
题目描述
代码结果
运行时间: 260 ms, 内存: 27.7 MB
// Java Stream API solution
// For this problem, the use of streams is not very efficient compared to the standard approach using deque,
// but we can still illustrate a functional approach. However, Java Stream API does not have direct support
// for efficiently solving this problem due to the need for maintaining a sliding window maximum.
// The solution provided uses imperative style because of the efficiency constraints.
// Here, we utilize the same deque method but just wrap it in stream-like operations.
import java.util.Deque;
import java.util.LinkedList;
import java.util.stream.IntStream;
public class Solution {
public int constrainedSubsetSum(int[] nums, int k) {
Deque<Integer> deque = new LinkedList<>();
return IntStream.range(0, nums.length).map(i -> {
if (!deque.isEmpty() && deque.peekFirst() < i - k) {
deque.pollFirst();
}
int max = nums[i] + (deque.isEmpty() ? 0 : Math.max(0, nums[deque.peekFirst()]));
while (!deque.isEmpty() && max > nums[deque.peekLast()]) {
deque.pollLast();
}
deque.offerLast(i);
return max;
}).max().orElse(0);
}
}
解释
方法:
这个题解使用了动态规划加单调队列的优化方法。动态规划数组`nums`的每个元素`nums[i]`被更新为以`nums[i]`结尾的最大子序列和。考虑到每个元素只能与前面距离不超过`k`的元素组成子序列,所以每次计算`nums[i]`时,只需要考虑`nums[i-k]`到`nums[i-1]`这个区间内的最大值。为了高效地获取这个区间内的最大值,使用了单调队列`stk`,这个队列存储的是索引,并且保证队列中的元素对应的`nums`值是单调递减的。对于每个新的`i`, 我们从队头移除超过距离限制的索引,然后将`nums[i]`与队头所指元素的`nums`值相加(如果这个值是正的),这样`nums[i]`就成了以`i`为结尾的最大子序列和。然后我们将当前的`i`添加到队列中,同时保持队列的单调性。这样,队列的头总是当前窗口的最大值。最终,遍历完成后的最大`nums`值即为答案。
时间复杂度:
O(n)
空间复杂度:
O(k)
代码细节讲解
🦆
为什么在动态规划中选择使用单调队列而不是其他数据结构如堆(优先队列)来维护区间最大值?
▷🦆
在题解中提到,如果队头元素的`nums`值是正的,则将其加到`nums[i]`上,这是否意味着如果队头元素的`nums`值为负或零则不进行加法操作?这样做的逻辑依据是什么?
▷🦆
题解中提到移除超出范围k的元素索引,这里的移除操作是如何确保算法的正确性的?即如何保证移除的总是正确的索引?
▷