算法学习|滑动窗口问题
问题描述
滑动窗口用于解决数组或字符串中子区间问题,尤其适用于需要处理连续区间的问题。
通过维护一个动态的窗口(通常由两个指针表示左右边界),在遍历过程中调整窗口的大小或位置,从而高效地解决问题。
一、滑动窗口的两种类型
-
固定大小的窗口
窗口长度固定,通过滑动窗口计算特定值(如最大值、平均值等)。 -
动态调整的窗口
窗口长度根据条件动态变化(如无重复字符的最长子串)。
二、固定大小窗口示例:连续子数组的最大平均值
问题:给定数组 nums 和整数 k,找到长度等于 k 的连续子数组的最大平均值。
算法步骤
- 计算初始窗口的和。
- 滑动窗口,每次减去左端元素,加上右端新元素。
- 更新最大值。
def find_max_average(nums, k):
window_sum = sum(nums[:k])
max_sum = window_sum
for i in range(k, len(nums)):
window_sum += nums[i] - nums[i - k]
max_sum = max(max_sum, window_sum)
return max_sum / k
nums = [1, 12, -5, -6, 50, 3]
k = 4
print(find_max_average(nums, k)) # 输出 12.75(子数组 [12, -5, -6, 50])
三、动态窗口示例:无重复字符的最长子串
问题:给定字符串 s,找到其中不含有重复字符的最长子串的长度。
算法步骤
- 使用左右指针定义窗口,用哈希表记录字符的最新位置。
- 右指针不断右移,若字符重复,更新左指针到重复位置的下一个。
- 更新最大窗口长度。
实现
def length_of_longest_substring(s):
char_map = {} # 记录字符最后出现的位置
left = max_len = 0
for right, char in enumerate(s):
if char in char_map and char_map[char] >= left:
left = char_map[char] + 1 # 移动左指针避免重复
char_map[char] = right
max_len = max(max_len, right - left + 1)
return max_len
# 示例
s = "abcabcbb"
print(length_of_longest_substring(s)) # 输出 3("abc")
四、滑动窗口的适用场景
- 连续子数组/子串问题
如最大和、最小长度、平均值等。 - 需要高效遍历的区间问题
将时间复杂度从暴力法的 O(n²) 优化到 O(n)。 - 常见题目
- 最小覆盖子串(LeetCode 76)
- 长度最小的子数组(LeetCode 209)
- 字符串的排列(LeetCode 567)
关键点总结
- 双指针:滑动窗口通常由左右指针 (
left,right) 定义。 - 哈希表辅助:用于快速判断重复或统计字符频率。
- 边界条件:注意处理空输入或无效参数(如
k=0)。

浙公网安备 33010602011771号