class Solution {
public double findMaxAverage(int[] nums, int k) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int num : nums) {
min = Math.min(min, num);
max = Math.max(max, num);
}
// the average of any subarray can not be less than min of nums or greater than max of nums
double lo = min;
double hi = max;
double precision = 1e-6;
// use binary search to find the max average that satisfies the condition
while (lo + precision < hi) {
double mid = (lo + hi) / 2;
if (hasAvg(nums, k, mid)) {
lo = mid;
} else {
hi = mid;
}
}
return lo;
}
// return if there's a subarray with length greater than k and an average greater or equal to target
private boolean hasAvg(int[] nums, int k, double target) {
double precision = 1e-6;
double[] tmp = new double[nums.length];
double[] prefixes = new double[nums.length];
// premin要设为0,因为如果window外面的大于0还不如只取window里面的
double preMin = 0;
double sum = 0;
// offset by target so that we can just see if the elements sums up to greater or equal to zero
for (int i = 0; i < nums.length; i++) {
tmp[i] = (double)nums[i] - target;
sum += tmp[i];
prefixes[i] = sum;
if (i >= k) {
// compare it with the minimum element within the elements
// before the start of current k length window
preMin = Math.min(preMin, prefixes[i - k]);
if (prefixes[i] - preMin >= precision) {
return true;
}
}
}
// because we did not check the window without previous element, this is the last chance
return prefixes[k - 1] >= precision;
}
}