【滑动窗口】无重复字符的最长子串

137 阅读2分钟

题目

思路

  • 既然是子串,那么就存在左边界右边界,这里用left表示左边界的下标、right表示右边界的下标
  • abcabcbb为例,看下不同左边界的情况下,对应的最长串是多少
    • abcabcbb
    • abcabcbb
    • abcabcbb
    • abcabcbb
    • abcabcbb
    • abcabcbb
    • abcabcbb
    • abcabcbb
  • 像不像一个蠕动的毛毛虫,右侧是毛毛虫的头,左侧是毛毛虫的尾,如果头遇到了和尾相同的,就开始缩尾巴。比如
    • abcabcbb -> abcabcbb 是头部遇到了a和尾巴的a相同,开始收尾巴,就变成了以b为尾巴(abcabcbb),然后头继续往前走,就变成了abcabcbb

      src=http___c-ssl.duitang.com_uploads_item_202003_29_20200329024918_QzacU.thumb.400_0.gif&refer=http___c-ssl.duitang.gif

  • 假设上面的毛毛虫例子很抽象,或者不明白为什么是毛毛虫。重新梳理,还是以上面的abcabcbb -> abcabcbb 为例
    • abcabcbb:当前情况下是满足左边距left最长的情况。left下标就结束了。不可能再长了。此时右边距是right
    • 在此情况下,就去看 left + 1为左边距的情况,而且可以肯定的是,left + 1 到right是100%满足不重复的
    • 在上面这个情况下,就固定了left + 1下标的左边距,右边距继续往右走,以此循环,直到左边距到最后

题解

var lengthOfLongestSubstring = function(s) {
    let max = 0; // 最大的长度,返回值
    const arr = []; // 用于存储left 到right之间的值
    let right = 0; // 右侧下标
    for (var left = 0; left<s.length;left++){ // 左边距从0开始
        arr.shift(); // 只要left左边距往右走一步,就要把第一位去掉,进入下一次循环
        while(right < s.length && !arr.includes(s[right])) { // 右边距往后走,如果没有重复的,放到arr中
            arr.push(s[right])
            right++ // 右坐标往后走
        }
        max = Math.max(arr.length, max) // 保存最大值
    }
    return max;
}

扩展