【LeetCode 热题 100】无重复字符的最长子串:滑动窗口解法详解
大家好!今天来拆解 LeetCode 热题 100 里的 **"无重复字符的最长子串"(中等难度),用滑动窗口 ** 思路轻松解决这个经典问题~
一、题目理解:子串≠子序列!
先明确题目的核心要求:给一个字符串s,找不包含重复字符的最长连续子串 的长度。注意:子串是连续的(比如 "pwke" 是 "pwwkew" 的子序列,但不是子串)。
二、思路:滑动窗口(双指针 + 哈希表)
这题的最优解法是滑动窗口,时间复杂度 O (n)(只遍历字符串一次),思路如下:
- 用左右指针维护一个 "当前无重复的子串窗口";
- 用数组 / 哈希表记录窗口内字符的出现次数;
- 右指针向右扩展窗口,若遇到重复字符,就移动左指针缩小窗口,直到无重复;
- 每次扩展后,更新 "最长子串长度"。
三、代码实现(C++)
直接看代码(附详细注释):
cpp
class Solution {
public:
int lengthOfLongestSubstring(string s) {
// 用数组v记录字符出现次数(ASCII字符共256种)
vector<int> v(256, 0);
int left = 0; // 左指针(窗口左边界)
int count = 0; // 记录最长子串长度
// 右指针遍历字符串(窗口右边界)
for(int right = 0; right < s.size(); right++){
v[s[right]]++; // 当前字符的出现次数+1
// 如果当前字符出现次数>1(有重复),移动左指针缩小窗口
while(v[s[right]] > 1){
v[s[left]]--; // 左指针指向的字符从窗口中移除
left++; // 左指针右移
}
// 更新最长子串长度(当前窗口长度是right-left+1)
count = max(count, right - left + 1);
}
return count;
}
};
四、代码解释:举个例子
以示例 1s = "abcabcbb"为例,走一遍流程:
- right=0(字符
a):v ['a']=1,窗口 [0,0],count=1; - right=1(字符
b):v ['b']=1,窗口 [0,1],count=2; - right=2(字符
c):v ['c']=1,窗口 [0,2],count=3; - right=3(字符
a):v ['a']=2→重复,移动 left 到 1,v ['a']=1,窗口 [1,3],count 保持 3; - ...... 后续继续维护窗口,最终 count=3(对应 "abc""bca" 等子串)。
五、为什么这么高效?
滑动窗口的核心是 **"窗口只右移,不回退"**:左指针和右指针都最多遍历字符串一次,所以时间复杂度是 O (n),空间复杂度是 O (1)(因为数组大小固定 256)。