【Medium】617. Maximum Average Subarray II
Given an array with positive and negative numbers, find the maximum average subarray which length should be greater or equal to given length k.
Notice:
It's guaranteed that the size of the array is greater or equal to k.
Example:
Given nums = [1, 12, -5, -6, 50, 3], k = 3
Return 15.667 // (-6 + 50 + 3) / 3 = 15.667
解题思路
用二分法进行夹逼。因为子数组的平均值一定在数组最大值和最小值之间,因此每次判断是否存在子数组使得平均值大于mid,如果存在,则向mid->max收敛,否则向min->mid收敛。
查询是否存在满足这样条件的子数组可以用prefiSum(前序和),prefixSum[i]指的是数组arr中从0到i的所有元素之和。满足条件的prefixSum[i]需要:
prefixSum[i] / ((i + 1) mid) - prefixSum[j] / ((j + 1) mid) >= 0
i - j >=k
用一个循环计算prefixSum[i],并且维护一个变量保存从0到i - k的最小prefixSum值(减数越小结果越大)。 当指针向后移,试图更新最小值的时候直接比较之前计算出的最小值和i - k + 1处的prefixSum值。 为了降低空间复杂度,直接用变量而不是数组存储prefixSum。
核心代码
返回类型:
class ResultType {
boolean exist;
int low;
int high;
ResultType(boolean e, int l, int h){
this.exist = e;
this.low = l;
this.high = h;
}
}
测试是否存在平均值大于等于mid的子数组:
private ResultType canFind(int[] nums, float mid, int k){
float prefixSumI = nums[0];
float prefixSumIminuxK = 0;
float Min = 0;
int minIndex = -1;
for (int i = 1; i < nums.length; i++){
prefixSumI += nums[i];
if (i >= k){
prefixSumIminuxK += nums[i - k];
}
if (i + 1 >= k && (prefixSumIminuxK - (i + 1 - k) * mid) <= Min){
Min = prefixSumIminuxK - (i + 1 - k) * mid;
minIndex = i - k + 1;
}
if (minIndex >= 0 && (prefixSumI - (i + 1) * mid) - Min >= 0){
return new ResultType(true, minIndex, i);
}
}
return new ResultType(false, -1, -1);
}
时间空间复杂度
O(n) + S(1)
n为数组长度
Last updated