|
|
package class40;
|
|
|
|
|
|
public class Code03_LongestLessSumSubArrayLength {
|
|
|
|
|
|
public static int maxLengthAwesome(int[] arr, int k) {
|
|
|
if (arr == null || arr.length == 0) {
|
|
|
return 0;
|
|
|
}
|
|
|
int[] minSums = new int[arr.length];
|
|
|
int[] minSumEnds = new int[arr.length];
|
|
|
minSums[arr.length - 1] = arr[arr.length - 1];
|
|
|
minSumEnds[arr.length - 1] = arr.length - 1;
|
|
|
for (int i = arr.length - 2; i >= 0; i--) {
|
|
|
if (minSums[i + 1] < 0) {
|
|
|
minSums[i] = arr[i] + minSums[i + 1];
|
|
|
minSumEnds[i] = minSumEnds[i + 1];
|
|
|
} else {
|
|
|
minSums[i] = arr[i];
|
|
|
minSumEnds[i] = i;
|
|
|
}
|
|
|
}
|
|
|
// 迟迟扩不进来那一块儿的开头位置
|
|
|
int end = 0;
|
|
|
int sum = 0;
|
|
|
int ans = 0;
|
|
|
for (int i = 0; i < arr.length; i++) {
|
|
|
// while循环结束之后:
|
|
|
// 1) 如果以i开头的情况下,累加和<=k的最长子数组是arr[i..end-1],看看这个子数组长度能不能更新res;
|
|
|
// 2) 如果以i开头的情况下,累加和<=k的最长子数组比arr[i..end-1]短,更新还是不更新res都不会影响最终结果;
|
|
|
while (end < arr.length && sum + minSums[end] <= k) {
|
|
|
sum += minSums[end];
|
|
|
end = minSumEnds[end] + 1;
|
|
|
}
|
|
|
ans = Math.max(ans, end - i);
|
|
|
if (end > i) { // 还有窗口,哪怕窗口没有数字 [i~end) [4,4)
|
|
|
sum -= arr[i];
|
|
|
} else { // i == end, 即将 i++, i > end, 此时窗口概念维持不住了,所以end跟着i一起走
|
|
|
end = i + 1;
|
|
|
}
|
|
|
}
|
|
|
return ans;
|
|
|
}
|
|
|
|
|
|
public static int maxLength(int[] arr, int k) {
|
|
|
int[] h = new int[arr.length + 1];
|
|
|
int sum = 0;
|
|
|
h[0] = sum;
|
|
|
for (int i = 0; i != arr.length; i++) {
|
|
|
sum += arr[i];
|
|
|
h[i + 1] = Math.max(sum, h[i]);
|
|
|
}
|
|
|
sum = 0;
|
|
|
int res = 0;
|
|
|
int pre = 0;
|
|
|
int len = 0;
|
|
|
for (int i = 0; i != arr.length; i++) {
|
|
|
sum += arr[i];
|
|
|
pre = getLessIndex(h, sum - k);
|
|
|
len = pre == -1 ? 0 : i - pre + 1;
|
|
|
res = Math.max(res, len);
|
|
|
}
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
public static int getLessIndex(int[] arr, int num) {
|
|
|
int low = 0;
|
|
|
int high = arr.length - 1;
|
|
|
int mid = 0;
|
|
|
int res = -1;
|
|
|
while (low <= high) {
|
|
|
mid = (low + high) / 2;
|
|
|
if (arr[mid] >= num) {
|
|
|
res = mid;
|
|
|
high = mid - 1;
|
|
|
} else {
|
|
|
low = mid + 1;
|
|
|
}
|
|
|
}
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
// for test
|
|
|
public static int[] generateRandomArray(int len, int maxValue) {
|
|
|
int[] res = new int[len];
|
|
|
for (int i = 0; i != res.length; i++) {
|
|
|
res[i] = (int) (Math.random() * maxValue) - (maxValue / 3);
|
|
|
}
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
System.out.println("test begin");
|
|
|
for (int i = 0; i < 10000000; i++) {
|
|
|
int[] arr = generateRandomArray(10, 20);
|
|
|
int k = (int) (Math.random() * 20) - 5;
|
|
|
if (maxLengthAwesome(arr, k) != maxLength(arr, k)) {
|
|
|
System.out.println("Oops!");
|
|
|
}
|
|
|
}
|
|
|
System.out.println("test finish");
|
|
|
}
|
|
|
|
|
|
}
|