leetCode第三题

81 阅读1分钟

前言:昨天过了个美好的 qi xi 节日,喝了点小酒,导致没完成,今天补回来补回来

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

  1. 解法一:(不推荐)

    1. 缺陷:1. 无法正确得到子串的数组 但是可以得到相同的长度 2. 遍历的更多次
    2. 时间复杂度:O(n)
    3. 空间复杂度:O(n)
    
    //借助Math.Max方法得到最大值的方式。
    
    // 1. 确定好数据结构 => 创建一个存储池 以及长度值为0
    // 2. 确定好操作方式 => 开始遍历对比
    var lengthOfLongestSubstring = function (s) {
    let array = [],len = 0;
    for(let i = 0; i< s.length; i++){     // n      
        if(array.indexOf(s[i]) === -1){   
            array.push(s[i])              // n - x
        }else{
        // 如果存在  则直接删除第一个
            array.shift();                // n - x
            i--;                          // n - x
            continue; //不再对len赋值
        }
        len = Math.max(len,array.length)  // n - y
    }
    
    return len
}

image.png

  1. 解法二:

    1. 减少了遍历次数
    2. 仍然没有得到正确的子串
var lengthOfLongestSubstring = function (s) {
    let array = new Array();
    let len = 0;

    for (let i = 0; i < s.length; i++) {
        // 存在即删除 (a)bca... 遇到有相同的之后 删除第一个然后以b开始为起点  以此类推 可得 
        if (array.indexOf(s[i]) > -1)   {array.splice(0, array.indexOf(s[i]) + 1); continue}

        array.push(s[i]);

        len = Math.max(len, array.length);
    }
    return len
}

image.png

解法三:(推荐)

1. 指针解法:
var lengthOfLongestSubstring = function (s) {
// 定义滑动窗口左右指针 l,r 以及字符串长度 n 最终结果 max
let l = 0,
    r = 0,
    n = s.length,
    max = 0,
    // 定义 set 用来记录当前已经出现过的字符,用来作为是否重复出现过的依据
    set = new Set()
// 约束窗口可滑动的范围:右指针不超过字符串长度,左指针不超过右指针
while (l <= r && r < n) {
    // 如果当前字符未记录过:
    // 1. 比较当前左右两指针间窗口大小和当前max大小,更新max
    // 2. 记录当前字符到set中
    // 3. 因为当前仍未发生重复,因此窗口可以继续扩大范围,右指针向右平移
    if (!set.has(s[r])) {
        max = Math.max(r - l + 1, max)
        set.add(s[r])
        r++
    } else {
        // 如果当前字符已经被记录过:
        // 1. 右指针保持不动
        // 2. 在set中移除左指针对应的字符 左指针右移缩小窗口大小
        set.delete(s[l])
        l++
    }
}
return max
}