给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function (s) {
let left=right=length= maxlength=0
let set = new Set()
while(right<s.length){
if(!set.has(s[right])){
set.add(s[right])
length++
if (length > maxlength) {
maxlength = length;
}
right++;
}else{
while(set.has(s[right])){
set.delete(s[left])
left++
length--
}
set.add(s[right])
length++
right++
}
}
return maxlength
}
算法的主要思路是维护一个滑动窗口,滑动窗口的左右端点分别是 left
和 right
,初始值都为 0。随着右端点 right
的不断移动,滑动窗口的大小也在不断变化。同时,使用集合 set
存储当前窗口中的字符,判断当前字符是否已经出现过。如果当前字符已经出现过,就将左端点 left
向右移动,同时将其从集合 set
中删除,直到窗口中不包含重复字符为止。
具体来说,算法执行的过程如下:
- 初始化滑动窗口的左右端点
left
、right
,以及滑动窗口的长度length
和最大长度maxlength
,初始值都为 0。 - 遍历字符串
s
,当右端点right
小于字符串的长度时,执行以下操作: 如果当前字符s[right]
没有在集合set
中出现过,则将其加入集合set
中,同时将滑动窗口的长度length
加 1。 如果当前字符s[right]
已经在集合set
中出现过,则需要将左端点left
向右移动,直到窗口中不包含重复字符为止。具体操作是,使用while
循环将左端点left
向右移动,每次删除集合set
中的一个字符,同时将滑动窗口的长度length
减 1。当集合set
中不再包含字符s[right]
时,退出循环。 在每次更新滑动窗口长度length
后,都需要判断是否超过了当前的最大长度maxlength
,如果是,则将其更新为当前的长度。 将右端点right
向右移动一位,继续执行循环。 - 循环结束后,返回最大长度
maxlength
。
总的来说,这段代码是一种简洁高效的求解最长不重复子串长度的算法,时间复杂度为 $O(n)$,空间复杂度为 O(n)。