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 <= A.length <= 50000
-10 ^ 5 <= A[i] <= 10 ^ 5
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;
}
}