🔥个人主页: Milestone-里程碑
❄️个人专栏: <<力扣hot100>> <<C++>><<Linux>>
🌟心向往之行必能至
📝 题目描述
给定一个字符串 s,请你找出其中不含有重复字符的最长子串的长度。
示例:
- 输入:
s = "abcabcbb" - 输出:
3 - 解释:因为无重复字符的最长子串是
"abc",所以其长度为 3。
💡 解题思路:滑动窗口
这道题的核心需求是「找到无重复的最长子串」,而滑动窗口正是处理这类子串 / 子数组问题的利器。
核心思想
我们可以把字符串想象成一条直线,用两个指针 left 和 right 维护一个动态的「窗口」:
- 右指针
right:负责向右扩展窗口,把新的字符加入窗口。 - 左指针
left:当窗口内出现重复字符时,向右移动以缩小窗口,直到窗口内不再有重复。 - 计数数组:用一个大小为 256 的数组记录每个字符在当前窗口中的出现次数,因为 ASCII 字符最多有 256 种。
这个过程就像一个滑动的窗口,右指针不断向右探索,左指针在必要时收紧,始终保证窗口内的字符是唯一的。
🧩 完整代码实现
cpp
class Solution {
public:
int lengthOfLongestSubstring(string s) {
// 初始化数组,记录每个字符出现次数,初始值为0
vector<int> v(256, 0);
int left = 0, count = 0;
// 右指针遍历整个字符串
for (int right = 0; right < s.size(); right++) {
// 当前字符加入窗口,计数+1
v[s[right]]++;
// 如果当前字符出现次数 > 1,说明窗口内有重复
while (v[s[right]] > 1) {
// 左指针右移,减少离开窗口的字符的计数
v[s[left]]--;
left++;
}
// 更新最长无重复子串的长度
count = max(count, right - left + 1);
}
return count;
}
};
⚙️ 复杂度分析
- 时间复杂度:O (n)每个字符最多被右指针和左指针各访问一次,总操作次数是 2n,所以是线性时间。
- 空间复杂度 :O (1)因为
vector的大小固定为 256,是一个常数,不随输入字符串长度变化。
✅ 测试用例验证
我们用题目中的几个示例来验证一下代码的正确性:
-
输入 :
"abcabcbb"窗口变化:a→ab→abc→bca→cab→abc→b→b最长长度为 3。 -
输入 :
"bbbbb"窗口始终只能包含一个b,最长长度为 1。 -
输入 :
"pwwkew"窗口变化:p→pw→w→wk→wke→ke→kew最长长度为 3。
🎯 总结
滑动窗口是一种非常高效的算法思想,尤其适合处理子串、子数组类的问题。这道题的关键在于:
- 用两个指针动态维护窗口的边界。
- 用数组快速判断字符是否重复。
- 在每一步更新最长子串的长度。