长>=k子段的最大均值
Given an array consisting of
nintegers, 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.
double findMaxAverage(vector<int>& nums, int k) {
// 最大均值一定在min(nums)和max(nums)之间
double l = INT_MAX, u = INT_MIN;
for (double num : nums) {
l = min(l, num);
u = max(u, num);
}
// 二分搜索猜
while (u - l > 1e-5) {
double mid = (l + u) / 2;
if (enough(mid, nums, k)) u = mid;
else l = mid;
}
return u;
}
bool enough(double m, vector<int> &nums, const int k) {
// "所有"长>=k的子段均值 (a[i]+a[i+1]+...+a[j])/(j−i+1) <= m
// a[i]+a[i+1]+...+a[j] <= m*(j−i+1),
// (a[i]−m)+(a[i+1]−m)+...+(a[j]−m)<=0 (1),
// (1)式左侧是关于m的递减函数,(1)式满足二分搜索的条件形式[0..0 1..1]
// (1)式可用累加数组sum[i]=(a[0]-m)+(a[1]-m)...+(a[i]-m)计算
// 对"所有"长>=k的子段,要 sum[j]-sum[i-1] <= 0,j-i+1>=k,
// 即要sum[j]-sum[ <=j-k ] <= 0,sum[j]-min{ sum[ <=j-k ] } <= 0
// 记currSum=sum[j],minPrevSum=min{ sum[ <=j-k ] },要currSum-minPrevSum<=0
double currSum = 0;
for (int j = 0; j < k; j++) {
currSum += nums[j] - m;
}
if (currSum > 0) return false;
double prevSum = 0, minPrevSum = 0;
for (int j = k; j < nums.size(); j++) {
currSum += nums[j] - m;
prevSum += nums[j-k] - m;
minPrevSum = min(minPrevSum, prevSum);
if (currSum - minPrevSum > 0) return false;
}
return true;
}