返回 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 <= A.length <= 50000
-10 ^ 5 <= A[i] <= 10 ^ 5
1 <= K <= 10 ^ 9
Review :
这道题真的是写了三遍....
为啥写了三遍... 第一次读错题了...我居然写成了最长的子数组..
然后我在最长子数组代码基础上改成了最短子数组...
由于逻辑不同超时...然后整理了下逻辑
得到了最优O(n) 最差O(n2)的答案
具体流程是遍历数组,累积前n项和,如果sum<=0,则起始指针前移;
当sum大于K时,反向贪心,起始指针能前移多少就前移多少,得到符合的值更新result
Code :
买一赠二: 赠超时版和最长子数组版
正版:
class Solution {
public int shortestSubarray(final int[] A, int K) {
int len = A.length;
int sum = 0, begin = 0, res = -1;
for (int i = 0; i < len; i++) {
if (A[i] >= K) return 1;
sum += A[i];
if (sum < 1) {
sum = 0;
begin = i + 1;
continue;
}
for (int j = i - 1; A[j + 1] < 0; j--) {
A[j] = A[j + 1] + A[j];
A[j + 1] = 0;
}
if (sum >= K) {
while (sum - A[begin] >= K || A[begin] <= 0)
sum -= A[begin++];
int length = i - begin + 1;
if (res < 0 || res > length)
res = length;
}
}
return res;
}
}
超时版:
public int shortestSubarray(int[] A, int K) {
int len = A.length;
int[] sum = new int[len + 1];
sum[1] = A[0];
for (int i = 1; i < len; i++)
sum[i + 1] = sum[i] + A[i];
int minLen = Integer.MAX_VALUE;
for (int i = 0; i < len; i++) {
if (i != 0 && A[i] >= K)
return 1;
for (int j = i + 1; j < len + 1; j++) {
if (sum[j] - sum[i] >= K) {
minLen = Math.min(minLen, j - i);
break;
}
}
}
return minLen == Integer.MAX_VALUE ? -1 : minLen;
}
看错题版(最长子数列):
//妈的做成最长的了
public int longestSubarray(int[] A, int K) {
int len = A.length;
int[] sum = new int[len + 1];
sum[1] = A[0];
for (int i = 1; i < len; i++)
sum[i + 1] = sum[i] + A[i];
int maxLen = -1;
for (int i = 0; i < len; i++) {
if (len - i < maxLen)
return maxLen;
for (int j = len - 1; j > i + maxLen - 1; j--)
if (sum[j] - sum[i] >= K)
maxLen = j - i + 1;
}
return maxLen;
}