题目
给定一个无序数组 arr,其中元素可正、可负、可 0。给定一个整数 k,求
arr 所有的子数组中累加和小于或等于 k 的最长子数组长度。
例如:arr = [3, -2, -4, 0, 6],k = -2,相加和小于或等于 -2
的最长子数组为 {3, -2, -4, 0},所以结果返回 4。
要求:时间复杂度为 \(O(N)\)。
解答
首先是 \(O(NlogN)\)
时间复杂度的解法,这个解法和之前的求解未排序数组中累加和为给定值的最长数组系列问题类似。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| public int maxLength(int[] arr, int k) { int[] helpArr = new int[arr.length + 1]; int sum = 0; helpArr[0] = sum; for (int i = 0; i != arr.length; i++) { sum += arr[i]; helpArr[i + 1] = Math.max(sum, helpArr[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(helpArr, sum - k); len = pre == -1 ? 0 : i - pre + 1; res = Math.max(res, len); } return res; }
public 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 - low) / 2; if (arr[mid] >= num) { res = mid; high = mid - 1; } else { low = mid + 1; } } return res; }
|
完美的 \(O(N)\)
的解法,这种解法也可以看成是 “滑动窗口” 的应用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public 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 res = 0; for (int i = 0; i < arr.length; i++) { while (end < arr.length && sum + minSums[end] <= k) { sum += minSums[end]; end = minSumEnds[end] + 1; } res = Math.max(res, end - i); if (end > i) { sum -= arr[i]; } else { end = i + 1; } } return res; }
|
测试
| public static void main(String[] args) { int[] arr = {0, 2, 5, 3, 2, -2, 1, -1}; int k = 3; GetMaxLengthAwesome_11 gmla = new GetMaxLengthAwesome_11(); System.out.println(gmla.maxLengthAwesome(arr, k)); System.out.println(gmla.maxLength(arr, k)); }
|
输出