3. Longest Substring Without Repeating Characters

该博客讨论了如何利用滑动窗口策略高效地解决LeetCode上的‘最长无重复字符子串’问题。文章比较了不同解法的时间复杂度和性能,包括使用数组和哈希映射的方法,并提供了多种解决方案的代码实现,如基于数组的优化解法和基于哈希映射的解法。这些解法的时间复杂度均为O(N),但通过数组实现能显著提高运行速度。
摘要由CSDN通过智能技术生成

Given a string s, find the length of the longest substring without repeating characters.

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters

LeetCode的运行时间很不稳定,最上面的三次使用完全相同的代码,但是结果相差很大,但仍然可以得知,采用数组比map大幅节省时间
LeetCode的运行时间很不稳定,最上面的三次使用完全相同的代码,但是结果相差很大,但仍然可以得知,采用数组比map大幅节省时间

更新最优解法:
思路来自于第二高赞
时间复杂度仍是O(N),但是时间大幅减少。
字符的数量有限,可以使用整型数组来代替map

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int last[128];
        int left=0;
        int maxlength=0;
        for(int i=0;i<128;i++){
            last[i]=-1;
        }
        for(int i=0;i<s.size();i++){
            int temp=int(s[i]);
            if(last[temp]>=0){//判断语句可有可无,对最终结果影响不大
                left=max(last[temp]+1,left);
            }
            last[temp]=i;
            maxlength=max(maxlength,i-left+1);
        }
        return maxlength;
    }
};

尝试的最优解法:
思路来自于最高赞评论
时间复杂度O(N)

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        map<char,int>m;
        int maxlength=0;
        int left=0;
        for(int i=0;i<s.size();i++){
            if(m[s[i]]!=0){
                //如果出现在map中,包含两种情况
                //left<=m[s[i]]-1,说明重复元素包含在当前字符串中,则最左边的下标更新为重复元素的后一个坐标
                //left>m[s[i]]-1,说明重复元素是之前出现的,不需要更新left的值
                left=max(m[s[i]],left);
            }
            m[s[i]]=i+1;//下标从0开始,为了防止和没有映射存在的情况混淆,统一加1
            maxlength=max(maxlength,i-left+1);
        }
        return maxlength;
    }
};

解题思路:
使用map记录每个字符是否出现,temp记录当前不重复的字符串。检测到重复的字符,删除temp中重复字符之前的字符,并在map中将对应字符的值置为0.更新最大长度。如果未检测到重复字符,则加在temp后面,map中字符的值置为1,长度加1.
最后再次比较length和longest的大小,取最大值

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        map<char,int>m;
        int longest=0,length=0;//longest目前为止最大的不重复串;length当前串的长度
        string temp="";
        for(int i=0;i<s.size();i++){
            if(m[s[i]]!=0){
                int j;   
                for(j=0;temp[j]!=s[i];j++){
                    m[temp[j]]=0;//清除重复字符及其前面的字符
                }
                if(j==temp.size()-1){
                    temp="";
                }else{
                    temp=temp.substr(j+1,-1);   
                }
                temp+=s[i];
                if(longest<length){
                    longest=length;
                }
                length=temp.size();
                m[s[i]]=1;//记录出现的位置
            }else{
                temp+=s[i];
                m[s[i]]=1;
                length++;
            }
        }
        if(longest<length){
            longest=length;
        }
        return longest;
    }
};

参考代码:
滑动窗口

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if(s.size() == 0) return 0;
        unordered_set<char> lookup;//无序集合
        int maxStr = 0;
        int left = 0;
        //find的返回值是一个迭代器(iterator),
        //如果找到了会返回指向目标元素的迭代器,没找到会返回end()
        for(int i = 0; i < s.size(); i++){
            while (lookup.find(s[i]) != lookup.end()){
          //如果当前元素已经包含在集合里面了,则去掉重合元素之前的元素
          //直到把重合的元素去掉,才会结束循环
          //left记录当前无重复字符串最左边的下标。先去掉,left向后移动
                lookup.erase(s[left]);
                left ++;
            }
            maxStr = max(maxStr,i-left+1);
            lookup.insert(s[i]);//把最新的元素加入到集合中
    }
        return maxStr;
        
    }
};

作者:powcai
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/hua-dong-chuang-kou-by-powcai/
来源:力扣(LeetCode)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值