返回

剑指 Offer II 041. 滑动窗口的平均值 : 从头轻松学会

后端

剑指 Offer II 041. 滑动窗口的平均值

题目

给你一个长度为 n 的整数数组 nums,以及一个整数 k。请你返回从数组 nums 中取出的任意连续子数组 [nums[i], nums[i+1], ..., nums[j-1], nums[j]] 的平均值,其中 0 ≤ i ≤ j < nj - i + 1 = k

示例

示例 1:

输入:nums = [1,3,-1,-3,5], k = 3
输出:[2,2]
解释:子数组的平均值为:
- [1,3,-1] 的平均值为 (1 + 3 - 1) / 3 = 2
- [3,-1,-3] 的平均值为 (3 - 1 - 3) / 3 = 2

示例 2:

输入:nums = [10,4,2,-1,6,5,-4,8,3,4,2,2,9,2], k = 5
输出:[7,7,7,7,4]
解释:移动窗口为 fixed-size (5)
- 第一个子数组:[10,4,2,-1,6], 平均值 = (10 + 4 + 2 - 1 + 6) / 5 = 7
- 第二个子数组:[4,2,-1,6,5], 平均值 = (4 + 2 - 1 + 6 + 5) / 5 = 7
- 第三个子数组:[-1,6,5,-4,8], 平均值 = (-1 + 6 + 5 - 4 + 8) / 5 = 7
- 第四个子数组:[6,5,-4,8,3], 平均值 = (6 + 5 - 4 + 8 + 3) / 5 = 7
- 第五个子数组:[-4,8,3,4,2], 平均值 = (-4 + 8 + 3 + 4 + 2) / 5 = 4

思路分析

本题属于「模拟」类型,核心思想是使用一个长度为 k 的队列来存储窗口中的元素,然后计算队列中所有元素的平均值,这就是窗口平均值。每当窗口移动一步,队列中的第一个元素就会被弹出,新的元素会被添加到队列中,然后重新计算队列中所有元素的平均值。

  • 使用队列来存储窗口中的元素。队列中的元素必须按顺序排列,且元素的数量必须始终等于窗口的大小 k
  • 使用 sum 变量来存储窗口中所有元素的和。当一个元素被添加到队列中时,将其添加到 sum 中,当一个元素从队列中弹出时,将其从 sum 中减去。
  • 使用 count 变量来存储窗口中的元素的数量。当一个元素被添加到队列中时,将 count 加一,当一个元素从队列中弹出时,将 count 减一。
  • 计算窗口中所有元素的平均值。平均值等于 sum 除以 count

实现

class MovingAverage:

    def __init__(self, size: int):
        self.size = size
        self.queue = collections.deque()
        self.sum = 0

    def next(self, val: int) -> float:
        self.queue.append(val)
        self.sum += val
        if len(self.queue) > self.size:
            self.sum -= self.queue.popleft()
        return self.sum / len(self.queue)

复杂度分析

  • 时间复杂度:O(n)。其中 n 是数组 nums 的长度。
  • 空间复杂度:O(k)。其中 k 是窗口的大小。

结语

本题是 leetcode 中的经典模拟题,通过使用队列来存储窗口中的元素,可以轻松的计算窗口平均值。希望这篇题解可以帮助你更好的理解这道题。

喜欢这道题目的话,记得点个赞,或者留言分享你的想法。