长>=k子段的最大均值

Given an array consisting of n integers, find the contiguous subarray whose length is greater than or equal to k that 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. 1 <= k<= n<= 10,000.
  2. Elements of the given array will be in range [-10,000, 10,000].
  3. 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;
}