【经典】单调队列+尺取法——leetcode 和至少为 K 的最短子数组

老经典题了,不过如果不是这题我差点忘了单调队列的性质。。平时做的几乎都是单调栈

这题和区间的和相关,那么首先弄一个前缀和出来(记得偏移一位,在前面补上个0),然后再遍历这个前缀和数组

遍历过程中维护一个单调队列deque

维护单调性:第i个元素进队时弹出后面所有不小于它的

尺取更新答案:完成上面一步后,只要队尾-队首>=K,说明可以更新答案,然后将队首元素弹出

class Solution {
public:
    int shortestSubarray(vector<int>& A, int K) {
        int n=A.size();
        for(int i=0;i<n;i++)if(A[i]>=K)return 1;
        
        vector<int>pre(n+1);
        pre[0]=0;pre[1]=A[0];
        for(int i=2;i<=n;i++)
            pre[i]=pre[i-1]+A[i-1];

        deque<int>dq;
        dq.push_back(0);
        int ans=n+1;
        for(int i=1;i<=n;i++){
            if(!dq.size()){dq.push_back(i);continue;}
            while(dq.size() && pre[dq.back()]>=pre[i])//元素入单调队列
                dq.pop_back();
            dq.push_back(i);

            //在单调队列上进行尺取
            while(dq.size()>=2){
                int dif=pre[dq.back()]-pre[dq.front()];
                if(dif>=K){
                    ans=min(ans,dq.back()-dq.front());
                    dq.pop_front();
                }else break;
            }
        }

        if(ans==n+1)ans=-1;
        return ans;
    }
};

 

posted on 2020-06-17 10:48  zsben  阅读(163)  评论(0编辑  收藏  举报

导航