大家好,我是唐叔,今天我们要一起学习一个在处理数组和字符串问题时非常高效的算法——滑动窗口算法。滑动窗口算法不仅能够帮助我们高效地解决一系列问题,还能让我们在处理复杂逻辑时更加得心应手。希望通过今天的分享,能够让各位读者朋友对滑动窗口算法有一个全面而深刻的理解。
滑动窗口算法概述
定义
滑动窗口是一种常用的算法技巧,主要用于处理数组或字符串的子区间问题。它通过维护一个窗口(即一个子区间),并在数组或字符串上滑动,来高效地找到满足条件的子区间。
应用场景
滑动窗口广泛应用于以下场景:
- 寻找最小子串:例如,给定两个字符串
s
和t
,找到s
中包含t
所有字符的最小子串。 - 计算子数组的和:例如,找到一个数组中和大于等于某个目标值的最短子数组。
- 统计子区间数量:例如,统计一个数组中满足某种条件的子区间的数量。
- 连续子字符串问题:例如,判断字符串中是否存在和为特定值的连续子字符串。
实现步骤
使用滑动窗口解决问题的一般步骤如下:
- 初始化窗口:定义两个指针
left
和right
,分别表示窗口的左边界和右边界。 - 扩展窗口:移动右指针
right
,扩大窗口,直到窗口内的元素满足某种条件。 - 收缩窗口:移动左指针
left
,缩小窗口,直到窗口内的元素不再满足某种条件。 - 记录结果:在每次窗口调整后,记录当前窗口的信息,如最长/最短子区间、满足条件的子区间数量等。
- 重复步骤2-4,直到右指针
right
达到数组或字符串的末尾。
注意事项
- 边界条件:处理边界条件时要特别小心,确保不会空窗口或窗口越界。
- 窗口大小:根据具体问题的需求,窗口大小可能是固定的,也可能是动态变化的。
- 窗口的滑动方向:可以是左移或右移,也可以是双向滑动。
- 条件判断:确保窗口的扩展和收缩逻辑正确,即条件判断的逻辑正确,避免遗漏或冗余。
LeetCode实战
入门题:3. 无重复字符的最长子串
题目链接:3. 无重复字符的最长子串
题目描述:给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
解题思路
这个问题非常适合用滑动窗口来解决。我们维护一个窗口 [left, right)
,并通过一个哈希表来记录窗口内字符的出现次数。当窗口内出现重复字符时,移动左指针 left
,直到窗口内没有重复字符。
Java代码实现
import java.util.HashMap;
import java.util.Map;
public class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> charIndexMap = new HashMap<>(); // 记录字符及其最近出现的位置
int le