Given an array consisting ofnintegers, find the contiguous subarray whose length is greater than or equal tokthat has the maximum average value. And you need to output the maximum average value.
Example 1:
Input: [1,12,-5,-6,50,3], k = 4
Output: 12.75
Explanation:
when length is 5, maximum average value is 10.8,
when length is 6, maximum average value is 9.16667.
Thus return 12.75.
Note:
1 <=k<=n<= 10,000.
Elements of the given array will be in range [-10,000, 10,000].
The answer with the calculation error less than 10^-5 will be accepted.
canBeLarger()的代码第一眼看不太好明白,这里要解释一下代码。我们需要三个变量, sum表示的是subarray[0, i]与target的差的累积和,preSum表示的是subarray[0, i - k]与target的差的累积和,minSum代表的是在[0, i - k]区间里最小的累积和。首先我们的目的是要在数组中找出长度至少为K的subarray,并且记录subarray上的数与target的差的累积和和0的大小关系。为了保证我们找到的subarray的长度至少为K,我们需要通过preSum记录与sum距离为k的subarray累积和。同时通过minSum我们可以知道[0, i - k]里的累积和中的最小数,如果sum >= minSum, 说明target比我们要找的maxAvg小,返回true。为什么要找[0, i - k]找到最小的累积和呢,如果最小的累积和与sum相减还是比0大,说明target一定比我们要找的maxAvg要大。
class Solution {
public double findMaxAverage(int[] nums, int k) {
int n = nums.length;
double res = Integer.MIN_VALUE;
for (int i = 0; i <= n - k; i++) {
double sum = 0;
for (int j = i; j < n; j++) {
sum += nums[j];
if (j - i + 1 >= k) {
res = Math.max(res, sum * 1.0 / (j - i + 1));
}
}
}
return res;
}
}
class Solution {
public double findMaxAverage(int[] nums, int k) {
double start = Integer.MAX_VALUE;
double end = Integer.MIN_VALUE;
for (int num : nums) {
start = Math.min(start, num);
end = Math.max(end, num);
}
while (end - start > 1e-5) {
double mid = start + (end - start) / 2;
if (canBeLarger(nums, k, mid)) {
start = mid;
}
else {
end = mid;
}
}
return start;
}
public boolean canBeLarger(int[] nums, int k, double target) {
double preSum = 0, minSum = 0, sum = 0;
for (int i = 0; i < k; i++) {
sum += nums[i] - target;
}
if (sum >= 0) {
return true;
}
for (int i = k; i < nums.length; i++) {
sum += nums[i] - target;
preSum += nums[i - k] - target;
minSum = Math.min(minSum, preSum);
if (sum >= minSum) {
return true;
}
}
return false;
}
}