leetcode-643. 子数组最大平均数 I

107 阅读2分钟

题目要求:

给你一个由 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

链接leetcode.cn/problems/ma…

解题思路

首先就想到的是滑动窗口,利用两个指针表示窗口的两边,左侧起始位是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
}