题目描述
给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度。
示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
提示:
0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成
思考
无重复字符的最长子串问题中,子串为连续字符且不可重复。由于需找最长子串,属于变长滑动窗口问题,可采用以下思路:
初始化左右指针均为0,用哈希表记录窗口内字符。右指针向右扩展,将字符加入哈希表;若遇重复字符,右移左指针收缩窗口,移除哈希表中对应字符,直至窗口无重复。过程中实时计算窗口长度(右减左加1),全局维护最大值。时间复杂度为O(n)O(n)O(n)(每个字符最多被两指针各访问一次),空间复杂度为O(n)O(n)O(n)(哈希表最多存储nnn个字符)。
算法过程
该算法通过滑动窗口结合哈希集合,高效寻找无重复字符的最长子串,过程如下:
-
初始化工具与指针
- 用
Set存储当前窗口中的字符(自动去重,便于快速判断重复)。 - 左指针
l与右指针r初始都为0,代表窗口起始位置;ans记录最长子串长度(初始为0)。
- 用
-
扩展右指针,扩大窗口
- 右指针
r从0开始遍历字符串s,每次尝试将s[r]加入窗口。
- 右指针
-
处理重复字符,收缩窗口
- 若
s[r]已在Set中(存在重复),则通过循环移动左指针l,并从Set中删除s[l],直到s[r]不在Set中(确保窗口内无重复)。
- 若
-
更新最长长度
- 将
s[r]加入Set,此时窗口[l, r]为无重复字符的子串,计算其长度r - l + 1,并更新ans为当前最大值。
- 将
-
返回结果
- 遍历结束后,
ans即为最长无重复子串的长度。
- 遍历结束后,
核心逻辑:通过右指针探索新字符,左指针在遇到重复时收缩至“重复字符的下一位”,始终保持窗口内无重复,同时实时记录最大窗口长度。时间复杂度 O(n)(每个字符最多被左右指针各访问一次)。
代码
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function(s) {
const set = new Set();
let l = 0, ans = 0;
for (let r = 0; r < s.length; r++) {
while (set.has(s[r])) {
set.delete(s[l]);
l++;
}
ans = Math.max(ans, r -l + 1);
set.add(s[r]);
}
return ans;
};
可视化

1041

被折叠的 条评论
为什么被折叠?



