返回 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
代码:
public class Solution {
public int shortestSubarray(int[] A, int K) {
int len = A.length, min = len + 1;
int sum[] = new int[len + 1];
for (int i = 0; i < len; i++) {
sum[i + 1] = A[i] + sum[i];
}
LinkedList<Integer> queue = new LinkedList<>();
for (int i = 0; i <= A.length; i++) {
// 步骤1,保证留在队列中的都是前缀和比sum[i]小的.
// 举个例子,有 m < n < i, 如果sum[m] >= sum[n],因此有A[m...n) <= 0.
// 当判断i时,可得,A[m...i) = A[m...n) + A[n...i),因为 A[m...n) <= 0,简单推理即可得A[n...i) >= A[m...i).
// 有上面的推断可以得出,如果A[m...i) >= K,那么A[n...i)也必然大于等于K,而[n...i)的长度明显比[m...i)短.
// 因此只需要比较i与n即可,而不必比较i与m,因此可以将m直接抛弃.
while (queue.size() > 0 && sum[i] <= sum[queue.getLast()]) {
queue.pollLast();
}
//步骤2. 如果满足,则去掉头部f,因为后面的下标p(p > i)即使满足 sum[p] - sum[f] >= k,那p - f的长度也比i - f的长度长.
while (queue.size() > 0 && sum[i] - sum[queue.getFirst()] >= K) {
min = Math.min(min, i - queue.getFirst());
queue.pollFirst();
}
queue.addLast(i);
}
return min <= len ? min : -1;
}
}