题目要求:
给你一个由 n 个元素组成的整数数组 nums 和一个整数 k 。
请你找出平均数最大且 长度为 k 的连续子数组,并输出该最大平均数。
任何误差小于 10-5 的答案都将被视为正确答案。
示例 1:
输入:nums = [1,12,-5,-6,50,3], k = 4
输出:12.75
解释:最大平均数 (12-5-6+50)/4 = 51/4 = 12.75
示例 2:
输入:nums = [5], k = 1
输出:5.00000
提示:
n == nums.length
1 <= k <= n <= 105
-104 <= nums[i] <= 104
解题思路
首先就想到的是滑动窗口,利用两个指针表示窗口的两边,左侧起始位是0,右侧起始位是k,遍历从第k位开始,到列表结束。中间每次计算均值,并且比较计算的均值和最大均值的大小,取大值。
代码如下:
func findMaxAverage(nums []int, k int) float64 {
if len(nums) == 1 && k == 1 {
return float64(nums[0])
}
// 滑动窗口,每次取k长度的数字,计算平均值
left, right := 0, k-1
res := -10001.0
for i := k; i <= len(nums); i++ {
result := count(nums[left : right+1])
if result > res {
res = result
}
left++
right++
}
return res
}
func max(a, b float64) float64 {
if a > b {
return a
}
return b
}
func count(nums []int) float64 {
total := 0
for _, v := range nums {
total += v
}
return float64(total) / float64(len(nums))
}
上边这个代码执行后,测试用例都通过了,但是超时了。看了题解发现是因为中间每次计算均值,这部分比较耗时,于是利用比较总和的方式,求出最大的和,那么该和对应的均值肯定是最大的均值,这样计算均值只需要一次即可。求总和也有个小细节,因为每次元素往后滑动一格,只需要减去上一次的第一个,加上当前元素的数值即可,第一次没有考虑到,用了for时间还是比较长。
改进后代码如下:
func findMaxAverage(nums []int, k int) float64 {
// 滑动窗口
sum := 0
for i := 0; i < k; i++ {
sum += nums[i]
}
maxSum := sum
for r := k; r < len(nums); r++ {
sum = sum -nums[r-k] + nums[r]
if maxSum < sum {
maxSum = sum
}
}
return float64(maxSum) / float64(k)
}
func max(a, b int) int {
if a > b {
return a
}
return b
}