LeetCode 👉 HOT 100 👉 无重复字符的最长子串 - 中等题

539 阅读3分钟

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

题目

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

示例1

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

示例2

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

示例3

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

思路

题目要寻找的是一个字符串的最长子串,很简单的就会想到,穷举这个字符串所有符合要求的子串,找出最长的那一个,即为题目所求

子串问题

这里考虑一个问题,假如从字符串的第一个位置开始找子串,记子串开始位置为 `i`

假如在后面的位置 `k + 1` 发现重复元素,意味着从 `i``k` 的子串是无重复的,长度为 `k - i + 1`;

那么在寻找下一个子串的时候,开始位置为 `i + 1`,从 `i + 1``k` 位置的子串一定也是符合要求无重复的子串
可以从 `k + 1` 开始判断下面的子串是不是符合要求,而不需要从 `i + 2` 开始

重复问题

这里可以使用 `Set`,因为可以很好的添加、删除以及判断元素是否存在

边界问题

输入的字符传长度为空,需要直接返回 0

代码如下

    /**
     * @param {string} s
     * @return {number}
     */
    var lengthOfLongestSubstring = function(s) {
        if(s === '') return 0;

        const strSet = new Set();
        const n = s.length;

        let ans = 0, right = -1;

        for(let i = 0; i < n; i++) {

            // 将窗口前部分后移
            if(i != 0) {
                strSet.delete(s.charAt(i - 1));
            }
            while(right + 1 < n && !strSet.has(s.charAt(right + 1))) {
                strSet.add(s.charAt(right + 1));
                // 将窗口后部分后移
                right++;
            }
            // 窗口滑动结束,保留我们需要的值
            ans = Math.max(ans, right - i + 1);
        }

        return ans;
    }

小结

上述的解法可以归纳为 滑动窗口,解法在不经意间,其实定义了两个指针 iright,每次循环都是判断从 iright 位置上的子串是不是符合要求,符合则将 right + 1,即把窗口向右移动,再次判断以 i 为起始位置的子串是不是符合要求;若移动过程中,不满足要求或者窗口滑到最后,则需要将窗口的前部分向右移动,再次判断以 i + 1 为起始位置的子串是不是符合要求;在滑动窗口的过程中,保留或者计算题目需要的值,等到整个窗口都滑动完成,保留的值即为题目所求

LeetCode 👉 HOT 100 👉 无重复字符的最长子串 - 中等题

LeetCode 👉 HOT 100 👉 两数相加 - 中等题

LeetCode 👉 HOT 100 👉 两数之和 - 简单题