无重复的最长子串(子串,滑动窗口)

168 阅读2分钟

思路

  • 重复字符涉及到关键词“重复,1次,出现次数”,这些情况一般可以考虑可以使用散列表,一般用字符作为键,次数或者索引作为值
  • 涉及子串,可以考虑使用滑动窗口来动态的扩张收缩子串
  • 设置一个rl指针,值动态的申明为遍历字符串的每一个i值索引,表示从当前i位置开始滑动窗口
  • 设置一个rk指针,当rl在当前i位置的时候,rk不断++,直到rl和rk之间将要出现重复字符串
  • 对于rl和rk之间的子字符保存,使用set数据的add和has方法保存和判断数据
  • 对于遍历字符串的过程中,每次i+1,set集合中保存的第一个数据将被剔除,每次k++,set中从末尾追加一个数据。
  • 考虑边界
    • 字符串为空,maxLength应该为0;

题目

给定一个字符串 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 由英文字母、数字、符号和空格组成

代码1(暴力求解 + 数组存储)

/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLongestSubstring = function(s) {
    let n = s.length;
    let maxLen = 0;
    let strArr = [];
    for(let i = 0;i < n;i++){
        if(strArr.includes(s[i])) {
           maxLen =  Math.max(maxLen,strArr.length);
            strArr = [];
            strArr.push(s[i]);
        } else {
            strArr.push(s[i]);
        }
    }
    return maxLen;
};

代码2滑动窗口

/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLongestSubstring = function(s) {
    let n = s.length;
    let occ = new Set()
    let rk = 0;
    let maxLen = 0;
    for(let i = 0;i < n;++i) {
        if(i != 0) {
            occ.delete(s[i-1]);
        }
        while(!occ.has(s[rk]) && ((rk ) < n)) {
            occ.add(s[rk],rk);
            rk++;
        }
        maxLen = Math.max(maxLen,(rk - i));
    }
    return maxLen;
};