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

返回 A 的最短的非空连续子数组的长度,该子数组的和至少为 K 。

如果没有和至少为 K 的非空子数组,返回 -1 。

 

示例 1:

输入:A = [1], K = 1
输出:1

示例 2:

输入:A = [1,2], K = 4
输出:-1

示例 3:

输入:A = [2,-1,2], K = 3
输出:3

 

提示:

  1. 1 <= A.length <= 50000
  2. -10 ^ 5 <= A[i] <= 10 ^ 5
  3. 1 <= K <= 10 ^ 9

Java

class Solution {
    public int shortestSubarray(int[] A, int K) {
        int n=A.length;
        int res=n+1;
        int[] B=new int[n+1];
        for(int i=0;i<n;i++)B[i+1]=B[i]+A[i];//Calculate prefix sum B of list A.
        //B[j] - B[i] represents the sum of subarray A[i] ~ A[j-1]
        Deque<Integer> d=new ArrayDeque<>();//Deque d will keep indexes of increasing B[i].
        for(int i=0;i<n+1;i++){
            //for B[i], find the smallest j that B[j] - B[i] >= K.
            //we start to compare B[i] with the smallest prefix sum in our deque, which is B[D[0]], hoping that B[i] - B[d[0]] >= K.
            while(!d.isEmpty()&&B[i]-B[d.getFirst()]>=K)
                res=Math.min(res,i-d.pollFirst());//if B[i] - B[d[0]] >= K, we can update our result res = min(res, i - d.popleft()).    
                //D[0] exists in our deque, it means that before B[i], we didn't find a subarray whose sum at least K. 
                //B[i] is the first prefix sum that valid this condition.
                //In other words, A[D[0]] ~ A[i-1] is the shortest subarray starting at A[D[0]] with sum at least K.
                //We have already find it for A[D[0]] and it can't be shorter, so we can drop it from our deque.
            while(!d.isEmpty()&&B[i]<=B[d.getLast()])//keep B[D[i]] increasing in the deque.
                //compared with d.back(),B[i] can help us make the subarray length shorter and sum bigger
                d.pollLast();//So no need to keep d.back() in our deque.
            d.addLast(i);
        }
        return res<=n? res:-1;
    }
}

cpp

class Solution {
public:
    int shortestSubarray(vector<int>& A, int K) {
        int N = A.size(), res = N + 1;
        deque<int> d;
        for (int i = 0; i < N; i++) {
            if (i > 0)
                A[i] += A[i - 1];
            if (A[i] >= K)
                res = min(res, i + 1);
            while (!d.empty() && A[i] - A[d.front()] >= K)
                res = min(res, i - d.front()), d.pop_front();
            while (!d.empty() && A[i] <= A[d.back()])
                d.pop_back();
            d.push_back(i);
        }
        return res <= N ? res : -1;
    }
};

py

class Solution:
    def shortestSubarray(self, A: List[int], K: int) -> int:
        d=collections.deque([[0,0]])
        res=float('inf')
        cur=0
        for i,a in enumerate(A):
            cur+=a
            while d and cur-d[0][1]>=K:
                res=min(res,i+1-d.popleft()[0])
            while d and cur<=d[-1][1]:
                d.pop()
            d.append([i+1,cur])
        return -1 if res==float('inf') else res

 

posted @ 2021-02-21 15:54  XXXSANS  阅读(81)  评论(0编辑  收藏  举报