1. 滑动窗口与双指针算法精讲
在算法竞赛和面试中,滑动窗口和双指针是解决子串、子数组类问题的两大核心技巧。这两种算法看似简单,但实际应用中却有着丰富的变体和精妙的优化空间。本文将深入剖析8道经典题目,从基础到进阶,带你掌握这些算法的精髓。
滑动窗口算法通常用于解决数组/字符串的子区间问题,通过维护一个动态变化的窗口来避免重复计算。而双指针则更灵活,可以是一前一后、同向移动或相向移动的不同组合。这两种算法的时间复杂度通常能达到O(n),是优化暴力解法的利器。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础题型解析
2.1 无重复字符的最长子串(LeetCode 3)
这是滑动窗口最经典的入门题。给定一个字符串,找出不含有重复字符的最长子串的长度。
解法思路:
- 使用哈希集合记录当前窗口内的字符
- 维护左右指针表示窗口边界
- 右指针不断右移,当遇到重复字符时,左指针移动到重复字符的下一个位置
python复制def lengthOfLongestSubstring(s: str) -> int:
char_set = set()
left = 0
max_len = 0
for right in range(len(s)):
while s[right] in char_set:
char_set.remove(s[left])
left += 1
char_set.add(s[right])
max_len = max(max_len, right - left + 1)
return max_len
复杂度分析:
- 时间复杂度:O(n),每个字符最多被访问两次(左右指针各一次)
- 空间复杂度:O(min(m,n)),m为字符集大小
注意:当输入字符串很长时,使用集合判断存在性比列表更高效。Python中集合的查找操作平均时间复杂度为O(1)。
2.2 长度最小的子数组(LeetCode 209)
给定一个正整数数组和一个正整数target,找出满足其和≥target的长度最小的连续子数组。
解法思路:
- 滑动窗口维护当前子数组的和
- 当和≥target时,记录长度并尝试缩小窗口
python复制def minSubArrayLen(target: int, nums: List[int]) -> int:
left = 0
current_sum = 0
min_len = float('inf')
for right in range(len(nums)):
current_sum += nums[right]
while current_sum >= target:
min_len = min(min_len, right - left + 1)
current_sum -= nums[left]
left += 1
return min_len if min_len != float('inf') else 0
常见错误:
- 忘记处理无解情况(返回0)
- 在缩小窗口时错误更新最小值
3. 进阶题型解析
3.1 至少有K个重复字符的最长子串(LeetCode 395)
找到字符串中最长的子串,要求其中每个字符出现的次数都不少于k次。
解法思路:
这道题需要分治思想结合滑动窗口:
- 统计整个字符串的字符频率
- 找到第一个不满足条件的字符作为分割点
- 递归处理分割后的子串
