Maximum Average Subarray
http://www.lintcode.com/en/problem/maximum-average-subarray/
Given an array with positive and negative numbers, find the maximum average subarray
which length should be greater or equal to given length k
.
Example
Given nums = [1, 12, -5, -6, 50, 3]
, k = 3
Return 15.667
// (-6 + 50 + 3) / 3 = 15.667
GetWay: 1. mid shoule locate in the range of min & max.
2. checkValid could check mid value. if mid is too small return true else return false;
3. when the value of r & l are nearlly same, then the average value is gotten.
4. in checkValid, sum[i] means that nums[i] - i * mid, cus it is in for loop, expression is diff.
5. preMin start with 0.0. after k index of nums, preMin should be checked. If the smaller value exists, then subsitute.
6. After k, sum[i] could be negtive, but sum[i] - preMin could be larger. And preMin constrained far away k index, such as sum[i - k + 1], it is nums[0] ~ nums[i - k] minus mid for every element.
Solution:
public double maxAverage(int[] nums, int k) {
if (nums == null || nums.length == 0) {
return 0.0;
}
double l = Double.MAX_VALUE;
double r = Double.MIN_VALUE;
double mid = 0.0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] < l) {
l = nums[i];
}
if (nums[r] > r) {
r = nums[i];
}
}
while (r - l >= 1e-6) {
mid = l + (r - l) / 2.0;
if (checkValid(nums, mid, k)) {
l = mid;
} else {
r = mid;
}
}
return l;
}
private boolean checkValid(int[] nums, double mid, int k) {
if (nums == null || nums.length == 0) {
System.out.println("checkValid function para error");
return false;
}
int n = nums.length;
double[] sum = new double[n + 1];
sum[0] = 0.0;
double preMin = 0.0;
for (int i = 1; i <= n; i++) {
sum[i] = sum[i - 1] + nums[i - 1] - mid;
if (i >= k && sum[i] - preMin >= 0) {
return true;
}
if (i > k) {
preMin = Math.min(preMin, sum[i - k + 1]);
}
}
return false;
}