原题
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
思路
本题同样是一道使用双指针思路(滑动窗口)的题目。
我们的start和end指针初始都是指向字符串的首部,紧接着end向后移动,每向后移动一步,都需要确认start和end之间的字符串是否有重复的字符。
使用什么方法确认,是否有重复的字符呢?如果直接使用字符串的api, 比如indexOf,每一次查询的时间复杂度是O(n)。我们可以使用hash,优化查询的过程,每一次使用hash查询的时间复杂度是O(1)。
当遇到重复的字符时,说明以当前start对应的字符,开头的最长的无重复字符的子串已经确定了。以start字符开头的字符已经不会有更长的无重复子串了。
我们需要将start的指针向前移动一步。然后重复上述的过程,直到end指针指向字符串的尾部结束。(已经指向尾部了,也不会有更长的子串了)

-
end向前递增

-
end向前递增

-
发现重复的字符。以开头a的为首的最长无重复字符子串,已经确定。我们可以将start指针向前诺一位

-
end向前递增

-
end向前递增

-
……重复上述的过程,直到end指向字符串的尾部,迭代结束。
代码
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function(s) {
const len = s.length
const hashMap = new Map()
let start = 0
let end = 0
let max = 0
while (end < len) {
if (!hashMap.has(s[end])) {
hashMap.set(s[end], end)
max = Math.max(max, hashMap.size)
end += 1
} else {
while (start <= hashMap.get(s[end])) {
hashMap.delete(s[start])
start += 1
}
hashMap.set(s[end], end)
end += 1
}
}
return max
};