LeetCode 862 和至少为K的最短子数组[前缀和 双端队列] HERODING的LeetCode之路

在这里插入图片描述
解题思路:
从求和再加上数组的长度,很容易联想到以空间换时间的方法——前缀和,由于数组中元素有负数,所以无法通过前缀和的单调性直接判断出结果,所以我们定义一个队列,用来存储已经访问过的前缀和下标,这些下标表示以该下标开始的序列目前还没找到满足条件的子序列,遍历每个前缀和,和队首进行比较,把所有满足条件的前缀和长度进行更新,并把队首出队列(已经找到满足条件的最短序列就不用留在队列中),同时对于留在队列中的前缀和下标,从队尾开始比较是否比当前前缀和大,大了也直接出队列,这相当于剪枝,因为保证序列最短,最后将当前前缀和放入队列中,代码如下:

class Solution {
public:
    int shortestSubarray(vector<int>& nums, int k) {
        int n = nums.size();
        vector<long> prefix(n + 1, 0);
        for(int i = 1; i <= n; i ++) {
            prefix[i] = prefix[i - 1] + nums[i - 1];
        }
        int minLen = INT_MAX;
        deque<int> q;
        for(int i = 0; i <= n; i ++) {
            long curSum = prefix[i];
            // 如果当前位置到队首的和满足k的条件
            while(!q.empty() && curSum - prefix[q.front()] >= k) {
                minLen = min(minLen, i - q.front());
                q.pop_front();
            }
            // 把队尾大的前缀和去掉
            while(!q.empty() && curSum <= prefix[q.back()]) {
                q.pop_back();
            }
            q.push_back(i);
        }
        return minLen == INT_MAX ? -1 : minLen;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

HERODING77

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值