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

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

示例 1:

输入: "abcabcbb"

输出: 3

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

示例 2:

输入: "bbbbb"

输出: 1

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

示例 3:

输入: "pwwkew"

输出: 3

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

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

这是一个简化版的滑动窗口题型。解题思路可以参考专题中关于双指针滑动窗口的相关介绍。

按照专题中的思路,这里考虑两点:

  1. 扩充右边界后,何时能使滑动窗口内的元素满足要求。根据题意,当滑动窗口的hash map中出现字符个数大于1的情况时,说明窗口中字串有重复字符,此时考虑开始缩小左边界。

  2. 何时更新返回结果。在本题中,当滑动窗口中所有元素个数都为1,则可以认为当前子串为无重复字符串,此时可以比对并更新结果。

function lengthOfLongestSubstring(s: string): number {
  const window: Record<string, number> = {};
  let res = 0;

  let left = 0;
  let right = 0;
  while (right < s.length) {
    // 扩大右边界
    const ch = s[right];
    right++;

    // 更新滑动窗口元素
    window[ch] = window[ch] ? window[ch] + 1 : 1;

    // 当滑动窗口中该字符个数大于1,此时字串不合法,需要缩小左边界直到使该字符唯一
    while (window[ch] > 1) {
      // 缩左边界
      const dropCh = s[left];
      left++;

      // 更新滑动窗口元素
      window[dropCh] -= 1;
    }

    // 更新合法情况的结果
    res = Math.max(res, right - left);
  }
  return res;
}