九章算法 | Google 面试题:子数组的最大平均值 II

给出一个整数数组,有正有负。找到这样一个子数组,他的长度大于等于 ​k​,且平均值最大。

  • 保证数组的大小 >= k

在线评测地址:LintCode 领扣

例1:

输入:
[1,12,-5,-6,50,3]
3
输出:
15.667
解释:
 (-6 + 50 + 3) / 3 = 15.667 

例2:

输入:
[5]
1
输出:
5.000 

算法:二分答案

本题看到以后先想到暴力,即枚举所有可能子数组,时间复杂度O(N^2)会超时,于是我们考虑更低复杂度的做法,是否有时间复杂度O(NlogN)级别的做法呢?我们考虑二分答案来解决问题。

算法思路

  • 我们考虑二分平均值,那么我们需要一个​check​函数,能在O(N)复杂度内判断是否存在一个子数组的平均值大于等于我们二分出来的平均值
  • 对于一个平均数​ave​,我们先将​nums​数组每个数减去​ave​,那么只要存在一个长度大于​k​的子数组和大于等于0,就说明平均数​ave​可行,这可以在O(N)时间内完成

代码思路

  1. 设置二分的左右边界分别为数组中的最小值和最大值
  2. 判断平均值​mid​是否可行,若可行则说明答案大于等于​mid​,那么左边界等于​mid​,否则说明答案小于​mid​,右边界等于​mid​
  • 如何判断平均值​mid​是否可行:
  1. 将​nums​数组每个数减去​mid​
  2. 求​nums​数组的前缀和数组​pre​
  3. 设置指针​index​等于k
  4. 那么在​nums[0:index]​中,长度大于​k​的子数组,区间和最大为​pre[index - 1] - min{pre[0 : index - k]}​
  5. 将​index​不断右移直到指向数组末端,若中间区间和最大值大于等于​0​,​check​函数直接返回​True​,结束后还为返回值则返回​False​
  6. 不断重复 2 直到 ​left + 1e-5 == right​ 退出
  7. 返回左边界

复杂度分析

NN表示​nums​数组长度,max_nums和min_nums分别表示数组中最大值和最小值

  • 空间复杂度:O(1)

实际处理时不需要记录下整个前缀和数组,只需记录当前的前缀和和左侧最小的前缀和

  • 时间复杂度:O(Nlog(max_nums−min_nums))
public class Solution {
     

 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值