未排序数组中累加和小于或等于给定值的最长子数组长度
给定一个无序数组arr,其中元素可正可负可0,给定一个整数k,求arr所有子数组中累加和小于或等于k的最长子数组长度。
例如:arr=[3,-2,-4,0,6], k=-2,相加和小于或等于-2的最长子数组为3,-2,-4,0 所以结果返回4
依次求以数组的每个位置结尾的,累加和小于或等于k的最长子数组长度,其中最长的那个子数组长度就是我们要的结果。
假如处理到位置30,从位置0到位置30的累加和是100(sum[0..30]=100),现在想求以位置30结尾的、累加和小于或等于10的最长子数组长度。再假设从位置0开始累加到位置10的时候,累加和第一次大于或等于90(sum[0..10]>=90),那么可以知道以位置30结尾的相加和小于或等于10的最长子数组就是arr[11..30]。也就是说,如果从0位置到j位置的累加和为sum[0..j],此时想求以j位置结尾的相加和小于或等于k的最长子数组长度。那么只要知道大于或等于sum[0..j]-k这个值的累加和最早出现在j之前的什么位置就可以,假设那个位置是i位置,那么arr[i+1..j]就是j位置结尾的相加和小于或等于k的最长数组。
由于不是具体值,而是范围值,所以不能直接用hashmap,为了方便地找到大于或等于某一个值的累加和最早出现的位置,可以按照如下方法生成辅助数组helpArr。
1.首先生成arr每个位置从左到右的累加和数组sumArr。以[1,2,-1,5,-2]为例,生成的sumArr=[0,1,3,2,7,5]。注意,sumArr中第一个数为0,表示当没有任何一个数时的累加和为0.
2.生成sumArr的左侧最大值数组helpArr,sumArr={0,1,3,2,7,5} -> {0,1,3,3,7,7}。因为我们只关心大于或等于某个值的累加和最早出现的位置,而累加和3出现在2之前,并且大于或等于3必然大于2,所以当前要保留一个更大的、出现更早的累加和。
3.helpArr是sumArr每个位置上的左侧最大值数组,那么它当然是有序的,在这样一个有序的数组中,就可以二分查找大于或等于某一个值的累加和最早出现的位置。例如,在[0,1,3,3,7,7]中查找大于或等于4这个值的位置,就是第一个7的位置
1 | public int maxLength(){ |