8.无重复字符的最长子串

112 阅读2分钟

题目链接

给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串(子字符串 是字符串中连续的 非空 字符序列。) 的长度。

示例 1:

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

示例 2:

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

示例 3:

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

题解1 暴力解法

思路

其实暴力解法最重要的就是读懂题目,题目想找出最长的子串,可以枚举每个字符为起点,往后枚举他的止点,顺便更新下答案。如果遇见相同字符,那么退出这个字符的枚举。

为了避免重复计算,如果从 i 开始往后都没有已知结果大,那么可以提前 return

代码

function lengthOfLongestSubstring(s: string): number {
    const set: Set<string> = new Set();
    let result: number = 0;
    for (let i = 0; i < s.length; i++) {
        for (let j = i; j < s.length; j++) {
            if (set.has(s[j])) {
                set.clear();
                break;
            } else {
                set.add(s[j]);
                result = Math.max(result, set.size);
            }
        }
        if (s.length - i < result) { // 剪一下枝 避免重复计算
            return result;
        }
        set.clear();
    }

    return result;
};

时空复杂度分析

时间复杂度:外层循环 O(n),内层循环最坏循环 O(n)。 总的复杂度为 O(n^2)

空间复杂度:使用了 set 来缓存已存在的字符串,复杂度为 O(n)

题解2 滑动窗口

思路

暴力解法的问题在于:

ij 的子串如果有重复字符,那么会从 i + 1j 重复进行遍历,而可能还是遍历到 j 遇到重复字符。它的下一次遍历并不保证会排除重复字符,所以造成了很多重复计算。

优化它的方式就是如果遇到重复子串,那么先把那个重复的字符给清空出去,然后再继续遍历。

有两种方式,一是用数组来维护,可以直接 shift(),二是用变量来维护。

代码

// 1.数组维护
function lengthOfLongestSubstring(s: string): number {
    const list: string[] = [];
    let result: number = 0;
    for (let char of s) {
        while (list.includes(char)) {
            list.shift();
        }
        list.push(char);
        result = Math.max(list.length, result);
    }

    return result;
};

// 2.变量维护
function lengthOfLongestSubstring(s: string): number {
    const map: Object = {};
    let result: number = 0;
    let left: number = 0;
    let right: number = 0;

    while (right < s.length) {
        if (map[s[right]]) {
            delete map[s[left]];
            left += 1;
        } else {
            map[s[right]] = 1;
            result = Math.max(result, right - left + 1);
            right += 1;
        }
    }

    return result;
};

时空复杂度分析

时间复杂度:数组维护最坏可能为 O(n^2),用变量维护为 O(n)

空间复杂度:因为要缓存当前维护的无重复子串,所有复杂度为 O(n)