Shortest Subarray with Sum at Least K

Return the length of the shortest, non-empty, contiguous subarray of A with sum at least K.

If there is no non-empty subarray with sum at least K, return -1.

Example 1:

Input: A = [1], K = 1
Output: 1

Example 2:

Input: A = [1,2], K = 4
Output: -1

Example 3:

Input: A = [2,-1,2], K = 3
Output: 3

Note:

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

思路:這題跟Minimum Size Subarray Sum 很相似,不同的是,加入了負數,使得問題變複雜了。思路就是:求區間和,很容易想到prefixsum,這個很好求出,但是怎麼掃描去求sum>=k的最小區間長度,sum[i] .... sum[j].... sum[k]

如果sum[i] > sum[j], sum[k] - sum[i] >=k, 那麼sum[k] - sum[j] 更加>=k,同時j > i,那麼j到k區間會更小,那麼sum[i]就沒必要存,發現這個性質那麼就是單調棧,但是sum[k] - sum[i] >= k ,那麼sum[i]會從前面踢掉,然而後面遇見i了,會把尾部的所有比他大的踢掉,後面又要進出,那麼我們用個deque就可以滿足上面兩個要求了。這裏要注意一點,長度是 i - deque.peekFirst()。爲什麼,是因爲sum[j] - sum[i] ,subarray的長度其實是i + 1,...j,那麼就是j - i + 1 - 1 = j - i;

class Solution {
    public int shortestSubarray(int[] A, int K) {
        int n = A.length;
        int[] sum = new int[n + 1];
        for(int i = 1; i <= n; i++) {
            sum[i] = sum[i - 1] + A[i - 1];
        }
        
        Deque<Integer> deque = new ArrayDeque<Integer>();
        int res = n + 1;
        for(int i = 0; i <= n; i++) {
            while(!deque.isEmpty() && sum[i] - sum[deque.peekFirst()] >= K) {
                res = Math.min(res, i - deque.pollFirst());
            }
            while(!deque.isEmpty() && sum[i] <= sum[deque.peekLast()]) {
                deque.pollLast();
            }
            deque.addLast(i);
        }
        return res <= n ? res : -1;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章