zoukankan      html  css  js  c++  java
  • LC 644. Maximum Average Subarray II 【lock,hard】

    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.

    求一个数组中长度大于等于K的子数组的平均值的最大值。

    我的AC解,这道题没什么思路,我只能暴力求解了,虽然AC但时间肯定长。

    Runtime : 1240ms  Beats:5.63%

    class Solution {
    public:
        double findMaxAverage(vector<int>& nums, int k) {
          vector<int> B(nums.size()+1);
          B[0] = 0;
          for(int i=1; i<B.size();i++){
            B[i] = B[i-1] + nums[i-1];
          }
          double sum = (double)INT_MIN;
          
          if(nums.size() < k) return 0;
          for(int i=k; i<B.size(); i++){
            for(int j=0; j+k<=i; j++){
              if(B[i] - B[j] > sum * (i - j)){
                sum = (double)(B[i]-B[j])/(i-j);
              }
            }
          }
          return sum;
        }
    };

     

    这是网上的解法,利用的是二分查找,但是这里的二分查找的判断条件不一样,是以平均值作为判断条件。

    我们要知道,一个数组的子数组的平均值介于这个数组最大值和最小值之间。因此可以将最大值和最小值的平均数mid作为判断依据,如果存在某一个长度大于K的子数组的平均数大于mid,那就说明

    需要从mid和最大值之间继续寻找。寻找次数是O(log(max + min)),每一次寻找都是遍历一遍数组O(n)。

    那如何通过遍历一遍数组来寻找是否存在一个长度大于K的子数组的平均数大于mid呢?先看代码,

    Runtime: 72ms, Beats: 90.14%

     

    整个程序结构right代表最大值,left代表最小值,整个程序大结构是一个while循环,判断条件是right和left差值小于0.00001,意思就是找到了题目要求的值。

    mid是最大值和最小值的平均数。

    利用sum求得数组累加和与mid的差值。因为我们想要比较长度大于K的所有数组和mid的大小关系,其实只需要比较长度大于K的所有数组中的最大值与mid的关系。

    而这个最大值和mid的关系可以用sum > minsum来表示,sum > minsum <=> sum - minsum > 0 <=> Σnums[i] - i * mid - minsum > 0 这个式子减号前一部分的意义好理解,

    就是前i个数组元素的和与i*mid的差,其实就是前i个数组元素的平均数与mid的差,minsum是第0个到第i-k个累加和中最小的一个和0的最小值,minsum初始值为0,

    所以碰到任何在0到i-k之间大于0的累加和全部为0,因为此时能让sum最大的情况是我把前i个元素都包括进来。

    如果碰到minsum小于0,假设这个minsum的index是第j个,也就是说第0到j个的累加和是小于0的,那这个时候,第j到i的累加和是要大于第0到i的累加和的,因为我们去掉了一些

    小于0的元素。取最小就是为了让sum最大。所以我们能得到长度大于K的所有数组的最大值与mid的关系。一旦得到了这个关系我们就知道他高于还是低于平均值mid,进而再

    用二分查找的思想迭代,得到最终的长度大于K的所有数组的最大值。

    后续:

    1. 如果要求长度大于K的所有数组的最小值怎么办?

    修改二分查找的时候right和left的赋值规则就行。很简单了。

     

  • 相关阅读:
    [SAP Rolling Out] Unit TEST/INTEGRATION TEST/UAT TEST/PARREL TESTING
    针式PKM与众不同的地方
    针式PKM拖动收集功能兼容所有的浏览器
    周九常:个人知识管理的三个重点领域
    关闭word文件老是说normal.dot被另外一人使用
    针式PKM初级应用:修改知识点的颜色评介
    寻找识货的人
    针式PKM中级应用如何将知识管理应用到新项目研发中
    针式PKM中级应用在10秒以内找到本月收集的任意文章
    针式PKM中级应用:知识点之间如何链接
  • 原文地址:https://www.cnblogs.com/ethanhong/p/10151170.html
Copyright © 2011-2022 走看看