当前位置 博文首页 > 文章内容

    【LeetCode-滑动窗口】最长不含重复字符的子字符串

    作者: 栏目:未分类 时间:2020-06-28 23:37:03

    本站于2023年9月4日。收到“大连君*****咨询有限公司”通知
    说我们IIS7站长博客,有一篇博文用了他们的图片。
    要求我们给他们一张图片6000元。要不然法院告我们

    为避免不必要的麻烦,IIS7站长博客,全站内容图片下架、并积极应诉
    博文内容全部不再显示,请需要相关资讯的站长朋友到必应搜索。谢谢!

    另祝:版权碰瓷诈骗团伙,早日弃暗投明。

    相关新闻:借版权之名、行诈骗之实,周某因犯诈骗罪被判处有期徒刑十一年六个月

    叹!百花齐放的时代,渐行渐远!



    题目描述

    请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。

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

    说明:

    • s.length <= 40000;
    • 这题是《剑指Offer》的第 28 题;

    题目链接: https://leetcode-cn.com/problems/zui-chang-bu-han-zhong-fu-zi-fu-de-zi-zi-fu-chuan-lcof/

    思路1

    使用滑动窗口来做。窗口的范围为 [left, right],left,right 初始化为0。设置一个查找表 lookup,lookup 存储了当前窗口中的元素。right 先移动,如果 s[right] 不在 lookup 中,则 right++,maxLen++,将 right 加入 lookup 中;否则,将 s[left] 从 lookup 中移除(注意这里不是先移除重复的元素 s[right],因为先移除 s[right] 的话就不满足连续子串这个要求了),将 left++,直至 s[right] 不在 lookup 中出现。代码如下:

    class Solution {
    public:
        int lengthOfLongestSubstring(string s) {
            if(s.empty()) return 0;
    
            unordered_set<char> lookup;
            int left = 0;
            int right = 0;
            int maxLen = 1; // 初始化为 1
            while(right<s.size()){
                if(lookup.count(s[right])==0){ // s[right]不在lookup中出现
                    lookup.insert(s[right]);
                    right++;
                    maxLen = max(maxLen, right-left);
                }else{
                    if(!lookup.empty()){
                        lookup.erase(s[left]);
                        left++;                    
                    }   
                }
            }
            return maxLen;
        }
    };
    

    思路2

    在思路 1 中,当遇到了重复字符,我们一步一步地移动 left 指针。为了加快速度,我们可以直接将 left 移动到当前 right 的位置上。
    代码如下:

    class Solution {
    public:
        int lengthOfLongestSubstring(string s) {
            if(s.empty()) return 0;
    
            vector<int> v(128, -1);
            int left = -1;
            int maxLen = 1;
            for(int right=0; right<s.size(); right++){
                char c = s[right];
                if(v[c]!=-1) left = max(left, v[c]);   // c 出现在了窗口中
                v[c] = right;
                maxLen = max(maxLen, right-left);
            }
            return maxLen;
        }
    };