滑动窗口


固定窗口与滑动窗口

1. 简介

固定窗口

  • 定义:窗口包含的元素个数(长度)始终保持不变。
  • 特点:移动时按固定步长整体平移,不会增减窗口内元素数量。
  • 适用场景:固定范围的统计或计算,比如固定时间窗口的接口限流、长度为 k 的子数组求和。

可变窗口

  • 定义:窗口长度可根据需求动态扩大或缩小,沿数据序列单向滑动。
  • 特点:通过调整左右边界控制窗口大小,避免重复计算,时间复杂度更低。
  • 适用场景:可变范围的序列问题,比如最长无重复子串、最小覆盖子串、满足条件的子数组个数。

核心区别

  • 窗口大小:固定窗口始终不变,滑动窗口可动态调整。
  • 移动逻辑:固定窗口是整体平移,滑动窗口是 “边界伸缩 + 滑动” 结合。
  • 效率侧重:固定窗口实现简单,滑动窗口在可变范围问题中更高效。

2. 案例与实现

1. 固定窗口

问题:给定数组 nums 和整数 k,求所有长度为 k 的连续子数组的最大和。

思路

  1. 先计算第一个窗口(前 k 个元素)的和;
  2. 滑动窗口时,每次减去窗口左侧离开的元素,加上右侧进入的元素,避免重复计算;
  3. 实时更新最大和。
def max_sum_fixed_window(nums, k):
    n = len(nums)
    if n < k or k <= 0:  # 边界条件
        return 0

    # 初始化第一个窗口的和
    current_sum = sum(nums[:k])
    max_sum = current_sum

    # 滑动窗口(从第 k 个元素开始)
    for i in range(k, n):
        # 移除左侧元素,加入右侧新元素
        current_sum = current_sum - nums[i - k] + nums[i]
        max_sum = max(max_sum, current_sum)

    return max_sum

# 测试
nums = [1, 3, -1, -3, 5, 3, 6, 7]
k = 3
print(max_sum_fixed_window(nums, k))  # 输出:16(对应子数组 [3,6,7])

2. 可变窗口

问题:给定字符串 s,找出其中不含有重复字符的最长子串的长度。

思路

  1. 用左右指针 leftright 维护窗口,right 向右扩展;
  2. 用哈希表 char_index 记录字符最后出现的位置;
  3. right 指向的字符已在窗口中(即 char_index[char] >= left),则将 left 移到该字符上次出现位置的右侧(保证窗口内无重复);
  4. 实时更新最长子串长度。
def length_of_longest_substring(s):
    char_index = {}  # 记录字符最后出现的索引
    max_len = 0
    left = 0  # 窗口左边界

    for right, char in enumerate(s):
        # 若字符已在当前窗口内,移动左边界到重复位置右侧
        if char in char_index and char_index[char] >= left:
            left = char_index[char] + 1

        # 更新字符最新位置和最大长度
        char_index[char] = right
        max_len = max(max_len, right - left + 1)

    return max_len

# 测试
s = "abcabcbb"
print(length_of_longest_substring(s))  # 输出:3(对应 "abc")

3. 简介算法可视化页面

窗口算法可视化

0 条评论

发表评论

暂无评论,欢迎发表您的观点!