题目
给定一个字符串,求不含重复字符的最长子串长度。
题目分析
这题最核心的不是枚举所有子串,而是维护一个始终“合法”的窗口。
所谓合法,就是窗口内没有重复字符。只要这个条件被破坏,就移动左边界把窗口收缩回来。
方法一:直觉解法
最直觉的做法是枚举所有子串,再判断是否有重复字符。这个思路容易想到,但复杂度会比较差。
方法二:优化思路
滑动窗口的关键动作是:
- 右指针不断向右扩张
- 一旦出现重复字符,左指针向右收缩
- 每次窗口合法时更新答案
一般会配一个哈希表来记录字符出现次数。
Go 实现
1func lengthOfLongestSubstring(s string) int {
2 counter := make(map[byte]int)
3 left, ans := 0, 0
4
5 for right := 0; right < len(s); right++ {
6 counter[s[right]]++
7 for counter[s[right]] > 1 {
8 counter[s[left]]--
9 left++
10 }
11 if width := right - left + 1; width > ans {
12 ans = width
13 }
14 }
15
16 return ans
17}
复杂度分析
- 时间复杂度:
O(n) - 空间复杂度:
O(k),k为字符集大小
易错点
- 更新答案要放在窗口已经恢复合法之后
- 左指针不是机械右移,而是要在“重复被消除”之前持续移动
我的复盘
滑动窗口看起来像技巧题,但本质上是在维护一个动态约束区间。把“窗口合法条件”想清楚,这类题就会稳定很多。