Leetcode 862. 和至少为 K 的最短子数组

题目

在这里插入图片描述
Leetcode 862. 和至少为 K 的最短子数组

代码(7.17 首刷看解析)

这是这几天以来做过最难的题了,这个题和Leetcode 209. 长度最小的子数组不一样,因为这个题有负数,如果用滑动窗口,一直加,就不会有答案。

用到了前缀和+单调队列

  1. 使用前缀和的差来计算子数组的和;
  2. 使用一种数据结构,将当前前缀和i与最前面的前缀和j作差,如果满足>=k的条件,那么j在之后就可以不用看了。【因为即使后面也有满足条件的,长度也会更长,所以需要将j从前面弹出】;
  3. 第2步完成了之后,当前的i也要放入数据结构,那么如果数据结构中有前缀和j比前缀和i大,j也可以不用看了。【因为即使后面有满足条件的,与i作差肯定也满足条件,并且长度更短,所以需要将大于等于i的从后面弹出】。
class Solution {
public:
    int shortestSubarray(vector<int>& nums, int k) {
        int n = nums.size();
        vector<long> preSumArr(n+1);
        for(int i = 0; i < n; i++) {
            preSumArr[i + 1] = preSumArr[i] + nums[i];
        }
        int res = n + 1;
        deque<int> q;
        for(int i = 0; i <= n; i++) {
            long curSum = preSumArr[i];
            while(!q.empty() && curSum - preSumArr[q.front()] >= k) {
                res = min(res, i - q.front());
                q.pop_front();  // 后续即使还有以它为起点的满足条件的子数组,长度也会大于当前的长度
            }
            while(!q.empty() && preSumArr[q.back()] >= curSum)
                q.pop_back();   // 作为减数时,更大的值只会让不等式更难满足;即使都满足,后访问到的值也可以带来更短的长度
            
            q.push_back(i);
        }
        return res == n+1 ? -1 : res;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值