前端算法(3)

112 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目

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

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

解题思路

思路一

我们先创建一个set,用来存放最长字符串,然后创建两个指针,left指向字符串开头,right随着for循环遍历字符串,for循环内部进行判断,如果set里面没有right指向的字符,则还没有重复的字符,将right指向字符添加到set中,更新最大子串的长度,也就是原来的result和现在的set大小进行比较,取最大值,如果set里面存在right指向的字符,则从set里删除left所指向的字符,缩小窗口,并且递增left,直到set里面没有right所指向的字符为止。这里需要注意的是缩小窗口需要使用while,不然只会执行一次,重复以上步骤,直到遍历完字符串

var lengthOfLongestSubstring = function(s) {
  const set = new Set();
  let result = 0, left = 0, right = 0;
  for(;right < s.length; right++){
      if(!set.has(s[right])){
          set.add(s[right]);
          result = Math.max(result,set.size);
      }else{
          while(set.has(s[right])){
                set.delete(s[left]);
                left++;
          }
          set.add(s[right])
      }    
  }
  return result;
};

思路二

var lengthOfLongestSubstring = function(s) {
    // 字符长度 <= 1 直接返回
    if (s.length <= 1) return s.length
    // 定义一个变量来存长度
    let max = 1
    // 定义一个 map 存子字符串
    let map = new Map()
    // 循环遍历
    for (let i = 0; i < s.length; i++) {
        // map 里没有直接设
        if (!map.has(s[i])) {
            map.set(s[i], s[i])
            // 判断一下 max 和 map.size 大小,把最大的给 max; (max = Math.max(max, map.size) 也可以)
            max = map.size > max ? map.size : max
        } else {
            // 判断一下是否是连续重复出现,重复出现直接把map清除再设值
            const prevStr = map.get(s[i - 1])
            if (prevStr === s[i]) {
                map.clear()
                map.set(s[i], s[i])
                max = max = map.size > max ? map.size : max
            }
            // 比如 12315689 1再次出现,第二个1之前的必须全部清除,因为是子串,不是子序列
            let mapArr = Array.from(map.keys())
            mapArr.slice(0, mapArr.lastIndexOf(s[i]) + 1).forEach(item => map.delete(item))
            map.set(s[i], s[i])
            max = map.size > max ? map.size : max
        }
    } 
    return max
};