给定一个无序数组arr,其中元素可正、可负、可0,给定一个整数k,求arr所有的子数组中累加和小于或等于k的最长子数组长度。
例如: arr=[3,-2,-4,0,6] , k=-2, 相加和小于或者等于-2的最长子数组为{3,-2,-4,0}, 所以结果返回4
解题思想(我称之为预处理思想):
预处理思想,把信息记录下来
累加和数组的改变
累加和数组中的最大值
用二分查找第一个大于等于某个值的位置
有序适合用二分查找
首先生成 sumArr 就是累加后的数组 这个数组大哦 因为 第一个为0 表示当没有任何一个数时的累加和为0
其次 生成sumArr的左侧最大数helpArr, sumArr={0,1,3,2,7,5} ->help={0,1,3,3,7,7} 我们只关心大于或等于某一个值的累加和最早出现的位置!
helpArr是sumArr每个位置上的左侧最大值数组,那么当然是有序的!
所以可以用二分查找法!查找大于或等于某一个值的累加和最早出现的位置。
package TT; public class Test72 { 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; } public static void main(String[] args){ int[] arr = new int[5]; arr[0]=3; arr[1]=-2; arr[2]=-4; arr[3]=0; arr[4]=6; int x = maxLength(arr,-2); System.out.println(x); } }