给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
思路:
1、遍历字符串
2、遍历的同时处理记录子串及相应的逻辑,应该怎么进行标记呢?
声明三个变量i,j,max
i用于记录当前子串的起点
j用于记录当前子串的终点
maxLength为当前最长的子串长度
声明一个容器,这边用set方便比较重复字符。
刚开始时当前子串起点和终点处于同一位置 i=j=0。
然后终点j往后移动一个位置,判断此时j位置的值子串里面是否存在:
存在的话: 统计当前子串的长度,对比当前maxLength的值,谁大取谁的值。然后起点位置i需要移动到子串里重复的值的后一个位置。如图:子串中存在j位置的值7,那么起点i位置应该移动到标记新起点的位置,即重复值7后一位。然后j继续往后移动,不断重复比较直到j移动到最后一个字符。
不存在的话: j往下移动一个位置,再按此规则继续重复比较
下面是具体代码实现:
function lengthOfLongestSubstring2 = function(s){
let i = j = 0, //标记起点终点位置
set = new Set(), //存储当前子串的容器,用于比较是否重复
maxLength = 0; // 存储字符串子串的最长长度
for(; j < s.length; j++){
// 当前set存储的子串是否含有j位置的字符
if(set.has(s[j])){
//存在重复的字符的话
maxLength = Math.max(maxLength, set.size) //存储子串最大长度
while(set.has(s[j])){
set.delete(s[i]) // 更新当前子串直到删除掉重复字符
i++ // i不断往后移动,直到重复值的下一个位置即可跳出循环
}
}
// 将j位置值存入set,等待j++进行下一次比较
set.add(s[j])
}
// 循环结束后还需比较最后一次容器存储的子串的长度(容易忽略)
maxLength = Math.max(maxLength, set.size)
return maxLength
}