题意
给定一个字符串,求不含重复字符的最长连续子串长度。
思路
标准滑动窗口:
- 右指针不断向右扩张,把新字符加入窗口。
- 如果出现重复字符,就移动左指针并清理计数。
- 每次维护窗口长度最大值。
这个题真正值得记住的不是代码,而是窗口的状态维护方式:
- 窗口里保存的是“当前合法区间”
- 重复条件出现时,只修复到重新合法为止
- 最大值更新通常放在窗口合法后
代码
int lengthOfLongestSubstring(string s) {
unordered_map<char, int> cnt;
int ans = 0;
for (int left = 0, right = 0; right < (int)s.size(); right++) {
cnt[s[right]]++;
while (cnt[s[right]] > 1) {
cnt[s[left]]--;
left++;
}
ans = max(ans, right - left + 1);
}
return ans;
}
易错点
- 不要在发现重复后只移动一次左指针,应该循环缩小窗口。
- 更新答案时机要在窗口恢复合法之后。
复杂度
- 时间复杂度:
O(n) - 空间复杂度:
O(字符集大小)
复盘
刷滑动窗口时,可以把题目先分类成:
- 固定窗口
- 最长合法区间
- 最短满足区间
这样在看到新题时更容易快速套框架。