LeetCode 643. 子数组最大平均数 I

题目链接

643. 子数组最大平均数 I

题目描述

给定一个整数数组 nums 和一个整数 k,找出长度为 k 的连续子数组的最大平均数,并返回该值。要求结果误差小于 10^-5

解法分析:滑动窗口法

核心思路

该解法采用滑动窗口技术,通过维护一个长度为 k 的窗口,遍历数组时动态计算窗口内元素的和,从而找到最大和,最终求得最大平均数。具体步骤如下:

  1. 右指针扩展窗口,累加当前元素到窗口和
  2. 当窗口长度达到 k 后,左指针开始滑动,每次减去窗口左边界元素
  3. 实时更新窗口内元素和的最大值,最后除以 k 得到最大平均数

代码实现

class Solution:
    def findMaxAverage(self, nums: List[int], k: int) -> float:
        from math import inf
        ans = -inf  # 最大子数组和
        l = 0       # 左指针
        s = 0       # 当前窗口和
        
        for r in range(len(nums)):
            s += nums[r]  # 累加当前元素到窗口和
            
            # 当窗口长度达到k时,开始滑动窗口
            if r + 1 >= k:
                ans = max(ans, s)      # 更新最大子数组和
                s -= nums[l]           # 减去左边界元素
                l += 1                 # 左指针右移,窗口滑动
        
        return ans / k  # 返回最大平均数

代码解析

  1. 初始化变量

    • ans:记录长度为 k 的子数组的最大和,初始化为负无穷
    • l:滑动窗口的左指针,初始位置为0
    • s:当前窗口内元素的和,初始为0
  2. 遍历数组

    • 右指针 r 从0开始遍历每个元素
    • s += nums[r]:将当前元素累加到窗口和中
  3. 窗口滑动逻辑

    • r + 1 >= k 时,说明窗口长度已达到 k(索引从0开始,r+1 表示当前窗口长度)
    • ans = max(ans, s):更新当前窗口内元素和的最大值
    • s -= nums[l]:减去左边界元素,为下一次窗口滑动做准备
    • l += 1:左指针右移,窗口向右滑动一位,保持窗口长度为 k
  4. 结果计算

    • 遍历结束后,ans 为长度为 k 的子数组的最大和,除以 k 得到最大平均数

关键逻辑说明

  • 窗口长度控制:通过 r + 1 >= k 判断窗口是否达到指定长度,确保窗口始终保持长度为 k
  • 动态求和:每次窗口滑动时,仅需更新左边界元素的加减,避免重新计算整个窗口和,时间复杂度从O(n*k)优化到O(n)
  • 最大值追踪:在窗口滑动过程中,实时更新最大子数组和,确保找到全局最大值

复杂度分析

  • 时间复杂度:O(n),其中 n 是数组长度。右指针遍历数组一次,左指针最多移动 n 次,总操作次数为 O(n)。
  • 空间复杂度:O(1),仅使用常数级额外空间存储指针和临时变量。

示例详解

以输入 nums = [1, 12, -5, -6, 50, 3], k = 4 为例:

  1. 初始化ans = -∞, l = 0, s = 0

  2. r=0,元素1

    • s = 0 + 1 = 1
    • r+1 = 1 < 4,不滑动窗口
  3. r=1,元素12

    • s = 1 + 12 = 13
    • r+1 = 2 < 4,不滑动窗口
  4. r=2,元素-5

    • s = 13 + (-5) = 8
    • r+1 = 3 < 4,不滑动窗口
  5. r=3,元素-6

    • s = 8 + (-6) = 2
    • r+1 = 4 >= 4,进入滑动:
      • ans = max(-∞, 2) = 2
      • s = 2 - nums[0] = 2 - 1 = 1
      • l = 1
  6. r=4,元素50

    • s = 1 + 50 = 51
    • r+1 = 5 >= 4
      • ans = max(2, 51) = 51
      • s = 51 - nums[1] = 51 - 12 = 39
      • l = 2
  7. r=5,元素3

    • s = 39 + 3 = 42
    • r+1 = 6 >= 4
      • ans = max(51, 42) = 51
      • s = 42 - nums[2] = 42 - (-5) = 47
      • l = 3
  8. 最终返回 51 / 4 = 12.75,符合示例输出。

总结

该解法利用滑动窗口高效解决了定长子数组的最大平均数问题,核心在于维护固定长度的窗口并动态更新和。滑动窗口技术在此类问题中具有显著优势:

  1. 避免了暴力枚举所有子数组的O(n²)复杂度
  2. 通过双指针移动实现线性时间复杂度
  3. 仅需常数空间存储临时变量

此方法适用于所有"定长子数组统计"问题,如子数组和、子数组最大值/最小值等,是算法设计中的基础技巧。计算平均数时需注意浮点数精度问题,但本题通过直接返回除法结果即可满足误差要求。

你可能感兴趣的:(滑动窗口与双指针,leetcode,算法,职场和发展)