题目描述
给定一个字符串 s
,请你找出其中不含有重复字符的 最长 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc"
,所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b"
,所以其长度为 1。
示例 3:
输入: s = "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是"wke"
,所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke"
是一个子序列,不是子串。
提示:
0 <= s.length <= 5 * 10^4
s
由英文字母、数字、符号和空格组成
解题思路
-
滑动窗口机制:
使用双指针left
和right
表示当前无重复子串的窗口。右指针right
逐步向右扩展窗口,左指针left
仅在发现重复字符时向右收缩。 -
字符位置记录:
用数组last_pos
记录每个字符最后出现的位置。数组大小为256,覆盖所有ASCII字符。 -
重复检测与窗口调整:
- 当右指针扫描到字符
s[right]
时,若该字符上次出现的位置在left
右侧(即last_pos[s[right]] >= left
),说明当前窗口内存在重复。此时将左指针移动到重复字符的下一个位置(last_pos[s[right]] + 1
),确保窗口内无重复。 - 更新当前字符的最新位置到
last_pos
中。
- 当右指针扫描到字符
-
动态更新最大长度:
每次扩展右指针后,计算当前窗口长度right - left + 1
,并更新全局最大值max_len
。
代码实现
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class Solution {
public:
int lengthOfLongestSubstring(string s) {
vector<int> last_pos(256, -1); // 存储字符最后出现的位置,ASCII扩展共256个字符
int max_len = 0;
int left = 0; // 滑动窗口左边界
for (int right = 0; right < s.size(); ++right) {
// 如果当前字符已在窗口中出现过,且位置在左边界右侧,则更新左边界
if (last_pos[s[right]] >= left) {
left = last_pos[s[right]] + 1;
}
// 更新当前字符的最后出现位置
last_pos[s[right]] = right;
// 计算当前窗口长度并更新最大值
max_len = max(max_len, right - left + 1);
}
return max_len;
}
};
效率分析
时间复杂度:
O(n),每个字符被访问一次,哈希表操作为常数时间。
空间复杂度:
O(1),固定大小的数组 last_pos
占用常数空间。