未排序数组中累加和小于或等于给定值的最长子数组长度
链接
来源:牛客网
给定一个无序数组arr,其中元素可正、可负、可0。给定一个整数k,求arr所有的子数组中累加和小于或等于k的最长子数组长度
例如:arr = [3, -2, -4, 0, 6], k = -2. 相加和小于等于-2的最长子数组为{3, -2, -4, 0},所以结果返回4
[要求]
时间复杂度为O(n),空间复杂度为O(n)
import java.util.*;
public class Main {
private static int solve(int[] arr, int k) {
int n = arr.length;
int[] minSum = new int[n];
int[] minSumEnd = new int[n];
minSum[n - 1] = arr[n - 1];
minSumEnd[n - 1] = n - 1;
for (int i = n - 2; i >= 0; --i) {
if (minSum[i + 1] <= 0) {
minSum[i] = minSum[i + 1] + arr[i];
minSumEnd[i] = minSumEnd[i + 1];
} else {
minSum[i] = arr[i];
minSumEnd[i] = i;
}
}
int ret = 0;
int sum = 0;
int end = 0;
for (int i = 0; i < n; ++i) {
while (end < n && sum + minSum[end] <= k) {
sum += minSum[end];
end = minSumEnd[end] + 1;
}
ret = Math.max(ret, end - i);
/**
* 说明没扩展成功
*/
if (i == end) {
end = i + 1;
} else {
sum -= arr[i];
}
}
return ret;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
int n = in.nextInt();
int k = in.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; ++i) {
arr[i] = in.nextInt();
}
System.out.println(solve(arr, k));
}
}
}
心之所向,素履以往 生如逆旅,一苇以航