[LeetCode 周赛186] 4. 带限制的子序列和(动态规划优化、优先队列、巧妙解法)

本文深入解析了一道动态规划优化问题——带限制的子序列和(LeetCode 5180),通过引入优先队列来降低时间复杂度至O(nlogn),并分享了代码实现细节。

1. 题目来源

链接:5180. 带限制的子序列和

2. 题目说明

在这里插入图片描述

3. 题目解析

方法一:dp优化+巧妙解法

属实没搞懂怎么下手…看了大佬的讲解很久…dp 蒻鷄太难了…

最大子序列问题的变种,也是一道 dp 优化问题。为什么需要优化呢,先来看看暴力 dp 的思路吧。

  • dp[i] 表示强制选择第 i 结尾的最大子序列的最大和值是多少
  • dp[i]=nums[i-1]+max{dp[j]},i-k<=j<i 时间复杂度 O ( n k ) O(nk) O(nk) 数据范围决定了,这个时间复杂度不理想状态下会达到 O ( n 2 ) O(n^2) O(n2),那么铁定 TLE

所以需要进行优化。优化思路如下:

  • max{dp[j]} 可以使用一个优先队列进行维护,队列元素为一个 pair 对,即 pair<dp[i], i>,那么在优先队列内会按照 dp[i] 从大到小存储,那么转移的时候取优先队列队头就行了。但同时需要满足 i-k<=j<i 这个条件,将条件进行转化那么就有 i - top.second > k 成立,即不在范围内的 top 元素将其 pop 出队,因为这个 dp[j] 对于以后的状态转移不会对后面的 dp[i] 造成影响了,即直接弹出队头
  • 若弹出还非空,那么 dp[i] 就从当前值和 ·top().first + 当前值 两者取最
    大值进行转移就可以了

这样做的目的就是使用优先队列成功将 max{dp[j]},i-k<=j<i 的时间复杂度降为 l o g log log 级的复杂度,那么整体复杂度即为 O ( n l o g n ) O(nlogn) O(nlogn) 是一个理想的复杂度情况了。

学的太渣了…dp 优化还没经历过,虽然感觉挺好理解的这种方法,但还是在本地进行了单步调试才理解了这个思想,确实强啊。近期也准备针对 dp 开始刷题了,希望能得到进步。

参见代码如下:

// 执行用时 :768 ms, 在所有 C++ 提交中击败了100.00%的用户
// 内存消耗 :157 MB, 在所有 C++ 提交中击败了100.00%的用户

#define PII pair<int, int>
#define MP(x, y) make_pair(x, y)

const int MAXN = 1e5 + 50;
priority_queue<PII> que;
int dp[MAXN];

class Solution {
public:
    int constrainedSubsetSum(vector<int>& nums, int k) {
        int n = nums.size();
        
        while(!que.empty()) que.pop();
        
        for (int i = 1; i <= n; i++){
            int v = nums[i - 1];
            dp[i] = v;
            while(!que.empty() and i - que.top().second > k) que.pop();
            if (!que.empty()) dp[i] = max(dp[i], que.top().first + v);
            que.push(MP(dp[i], i));
        }
        
        int ans = dp[1];
        for (int i = 2; i <= n; i++) ans = max(ans, dp[i]);
        return ans;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ypuyu

如果帮助到你,可以请作者喝水~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值