Skip to content

无重复字符的最长子串

中等

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

示例 1:

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

示例 2:

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

示例 3:

输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

提示:

  • 0 <= s.length <= 5 * 104
  • s 由英文字母、数字、符号和空格组成

题解

以字符串'abcabcbb'为例,从第一个字符开始循环遍历,找出不包含重复字符的最长子串
     以   (a)bcabcbb     开始的最长字符串为  (abc)abcbb     3
     以   a(b)cabcbb     开始的最长字符串为  a(bca)bcbb     3
     以   ab(c)abcbb     开始的最长字符串为  ab(cab)cbb     3
     以   abc(a)bcbb     开始的最长字符串为  abc(abc)bb     3
     以   abca(b)cbb     开始的最长字符串为  abca(bc)bb     2
     以   abcab(c)bb     开始的最长字符串为  abcab(cb)b     2
     以   abcabc(b)b     开始的最长字符串为  abcabc(b)b     1
     以   abcabcb(b)     开始的最长字符串为  abcabcb(b)     1
最终的结果是3

可以发现一个规律,开始字符串和结束字符串都是递增的
这样就可以使用滑动窗口来解决这个问题了
滑动窗口需要两个指针,左指针用来指向开始的字符,右指针用来指向结束的字符
由于需要循环,左指针借助每次循环的那个i

代码如下

  • 使用了一个数组来存储没重复的字符
  • shift 方法来实现左指针前进
  • includes 方法判断是否为重复子串
  • 也可以使用 Set 来实现
JavaScript
var lengthOfLongestSubstring = function (s) {
  // 右指针
  let rk = -1;
  // 用来保存字符串
  const arr = [];
  // 用来保存最长子串的长度
  let ans = 0;
  // 字符串长度
  let n = s.length;

  for (let i = 0; i < n; i++) {
    // 左指针前进
    if (i !== 0) arr.shift();

    while (!arr.includes(s[rk + 1]) && rk + 1 < n) {
      // 如果没有重复字符则把当前字符放入数组中
      arr.push(s[rk + 1]);
      // 右指针前进
      rk++;
    }
    // 取较大值
    ans = Math.max(arr.length, ans);
  }
  return ans;
};
例如字符串 abcabcbb
每次判断当下一个字符不重复时,右指针则向前移动

第一次循环
     一开始的下一个字符为a,右指针前进 [a]bcabcbb
     下一个字符b,右指针前进 [ab]cabcbb 
     下一个字符c,右指针前进 [abc]abcbb 
     下一个字符a,重复,长度为3,结束

第二次循环
     左指针前进 a[bc]abcbb
     下一个字符a,右指针前进 a[bca]bcbb
     下一个字符b,重复,长度为3,结束

第三次循环
     左指针前进 ab[ca]bcbb
     下一个字符b,右指针前进 ab[cab]cbb
     下一个字符c,重复,长度为3,结束

第四次循环
     左指针前进 abc[ab]cbb
     下一个字符c,右指针前进 abc[abc]bb
     下一个字符b,重复,长度为3,结束

第五次循环
     左指针前进 abca[bc]bb
     下一个字符b,重复,长度为2,结束

第六次循环
     左指针前进 abcab[c]bb
     下一个字符b,右指针前进 abcab[cb]b
     下一个字符b,重复,长度为2,结束

第七次循环
     左指针前进 abcabc[b]b
     下一个字符b,重复,长度为1,结束

第八次循环
     左指针前进 abcabcb[]b
     下一个字符b,右指针前进 acbabcb[b]
     遍历完成,长度为1,循环结束