具体地,如何检验当前候选平均值是否存在呢。我们维持一个sums累加数组(sums[i]存放的是sum[nums[0:i]]),但是累加的不是原来的nums[i]而是nums[i] - 候选avg,这样我们只要找是否有长度不小于k且和大于等于0的子数组。如何找到长度不小于K的呢?我们只要限制 min_pre 为 i - k 之前的最小前缀和即可。
Python Code:
classSolution:# @param {int[]} nums an array with positive and negative numbers# @param {int} k an integer# @return {double} the maximum averagedefmaxAverage(self,nums,k):# 检查长度 >= k 平均值 >= q 的subArray 是否存在defisValid(nums,k,target): sums =[0for i inrange(len(nums)+1)] min_pre =0for i inrange(1, len(nums)+1):# target 即为候选avg,累加数组sums sums[i]= sums[i -1]+ nums[i -1]- targetif i >= k:# i-k 保证了最终结果是长度不小于k的子数组 min_pre =min(min_pre, sums[i - k])if sums[i]- min_pre >=0:returnTruereturnFalse# use min and max as bounds to do binary search p =min(nums) r =max(nums)while r - p >1e-6: q =(p + r)/2.0ifisValid(nums, k, q): p = qelse: r = qreturn p
public class Solution {
/*
* @param nums: an array with positive and negative numbers
* @param k: an integer
* @return: the maximum average
*/
public double maxAverage(int[] nums, int k) {
int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE;
for (int num : nums) {
min = Math.min(min, num);
max = Math.max(max, num);
}
double left = min, right = max;
while (right - left > 1e-7) {
double mid = (left + right) / 2;
if (isValid(nums, k, mid)) {
left = mid;
} else {
right = mid;
}
}
return left;
}
private boolean isValid(int[] nums, int k, double avg) {
double[] prefix = new double[nums.length + 1];
double preMin = Integer.MAX_VALUE;
for (int i = 0; i < nums.length; ++i) {
prefix[i + 1] = prefix[i] + nums[i] - avg;
if (i >= k - 1) preMin = Math.min(preMin, prefix[i - k + 1]);
if (prefix[i + 1] - preMin > 0) return true;
}
return false;
}
}