# [3] 无重复字符的最长子串

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: "abcabcbb"

输出: 3

解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: "bbbbb"

输出: 1

解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: "pwwkew"

输出: 3

解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。

请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

这道题我们很容易想到暴力法,利用快慢指针,遍历字符串时,每次都检查当前字符是否在快慢指针之间的子串中存在,这里的快慢指针实际上形成了一个滑动窗口。

至于如何检查某个字符在子串中是否存在,我们可以直接遍历,也可以利用hash表进行优化。

  1. 若不存在该字符,则直接加上,值为当前字符的位置。
  2. 若存在该字符,则比对字符是否在滑动窗口内,若在,则说明当前子串存在重复字符。将慢指针移动到子串中重复字符的后一个位置以将重复字符剔除出滑动窗口,并继续向后遍历。

我们另外需要一个变量来记录遍历过程中的最长子串长度。遍历时,若当前子串长度长于记录值,则更新记录值即可。

var lengthOfLongestSubstring = function(s) {
  const len = s.length;
  let res = 0;
  const hash = {};
  let start = 0;
  for (let i = 0; i < len; i++) {
    if (hash[s[i]] !== undefined && hash[s[i]] >= start) {
      start = hash[s[i]] + 1;
    }
    hash[s[i]] = i;
    if (i - start + 1 > res) {
      res = i - start + 1;
    }
  }
  return res;
};