前端必刷算法题:“无重复字符的最长子串”

159 阅读2分钟

这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

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

 

示例 1:

输入: s = "abcabcbb"

输出: 3

解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: s = "bbbbb"

输出: 1

解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: s = "pwwkew"

输出: 3

解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。   请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

示例 4:

输入: s = ""

输出: 0

 

提示:

0 <= s.length <= 5 * 104

s 由英文字母、数字、符号和空格组成

1.暴力求解法

基本方法:

  1. 逐个生成子字符串
  2. 看他是否含有不重复字符

复杂度分析

时间复杂度:

  • 找到所有子串: O(n*n)
  • 判断子串是否仅含有唯一字符:Hash Set O(n),双指针 O(n*n)
  • 整体复杂度 : O(nnn)

空间复杂度:

  • Hash Set O(m)

可以看到暴力求解法是可以解出来,但是时间复杂度会达到 O(nnn),会有超时的风险。那么有没有优化的解法呢,答案是有的。利用new set() + 滑动窗口法。

2.new set() + 滑动窗口法

整体思路:

1.首先我们需要建一个set,来存放不重复的子串

2.之后通过滑动窗口来进行遍历寻找。

3.遍历所有字符,找出以不同下标字符为开头的最大不重复子串的长度。

/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLongestSubstring = function(s) {
    let occ = new Set();
    let n  = s.length;

    let rk = -1;
    let ans = 0;
    for(let i =0;i<n;++i){
        if(i!=0){
            occ.delete(s.charAt(i-1))
        }


        while(rk+1<n&& !occ.has(s.charAt(rk+1))){
            occ.add(s.charAt(rk+1));
            ++rk;
        }

        ans = Math.max(ans,rk-i+1)
    }
    return ans;
};

总结: 今天又是打卡算法题的一天,这个算法题在我参与前端面试的时候经常被提到过,但是还是没有成功做出来,就算用暴力解法解开还会有更优的方法等你,所以遇到这种题就要多刷然后把它吃透