给定一个无序数组arr,其中元素可正、可负、可0。给定一个整数k,求arr所有的子数组中累加和小于或等于k的最长子数组长度
例如:arr = [3, -2, -4, 0, 6], k = -2. 相加和小于等于-2的最长子数组为{3, -2, -4, 0},所以结果返回4
[要求]
时间复杂度为,空间复杂度为
第一行两个整数N, k。N表示数组长度,k的定义已在题目描述中给出
第二行N个整数表示数组内的数
输出一个整数表示答案
5 -2 3 -2 -4 0 6
4
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] params = br.readLine().split(" "); int n = Integer.parseInt(params[0]), k = Integer.parseInt(params[1]); String[] strArr = br.readLine().split(" "); int[] arr = new int[n]; for(int i = 0; i < n; i++) arr[i] = Integer.parseInt(strArr[i]); // minSums[i]表示从i开始,往后数组的最小和;minSumEnds[i]表示这个最小和数组的边界 int[] minSums = new int[n], minSumEnds = new int[n]; minSums[n - 1] = arr[n - 1]; minSumEnds[n - 1] = n - 1; for(int i = n - 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, sum = 0, maxLen = 0; for(int i = 0; i < n; i++){ while(end < n && sum + minSums[end] <= k){ // 满足累加和小于等于k就累加上 sum += minSums[end]; end = minSumEnds[end] + 1; } maxLen = Math.max(maxLen, end - i); if(end > i){ sum -= arr[i]; // 窗口内还有救,把左边的元素弹出去试试 }else{ end = i + 1; // 窗口内没救了,另起一个起点 } } System.out.println(maxLen); } }