前端Top100算法题---Top1. 无重复字符的最长子串

108 阅读1分钟

无重复字符的最长子串

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情

一般解法:滑动窗口

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

先从暴力解法入手

想得到答案,需要对比所有可能的结果

于是需要循环字符串s,以当前位置 index 为起点,计算每个位置的子串

使用数组记录当前位置的子串,循环位于 index 之后的字符,添加到数组中,直到出现数组中重复的字符。为了方便判断,数组可以优化为 set

最后比较所有的结果,得出最后的结果。这里不必存所有的结果,可以使用一个 ans 变量,只记录最大的结果即可

计算最长子串的过程可以使用滑动窗口优化

因为如果 index 0 的最长子串长度为 rk

那么,在计算 index 1 的最长子串时,是没有必要从 index 1 开始的

因为 index1 --> rk 这段在 index 0 时已经判断过,是必然不重复的。 所以,index 1 可以直接从 rk+1 开始判断

此时 index -> rk 就相当于窗口,窗口的大小在计算 index 位置的最长子串时不断增加,作为下一个位置 index+1 计算时优化的依据

  • 难点1:rk 的初始值为 -1,也就是窗口最小为 -1
  • 难点2:要记得每次循环开始时,把上一个字符从 set 中去掉(index 0 时除外)

Follow Up

一般公司对前端的算法要求,可能不会再追问了

如果要追问的话,最可能是,如果允许重复一次字符怎么办等等

可以参考 LeetCode 395 424 2024。。。