LeetCode 3 无重复字符的最长子串 滑动窗口方法

题目链接

  1. 无重复字符的最长子串
    给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
    示例 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 由英文字母、数字、符号和空格组成
    通过次数993,207提交次数2,673,442

解题思路: 滑动窗口

AC代码:

/*
    维护一个区间的左边界和右边界
    如果没有重复的元素就不断从右边放入元素
    否则就从左端点不断删除元素
    时间复杂度O(n)
*/
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int left=0, right=0, len=s.length(),maxlen=0;
        //根据题意,256大小的整型数组足以跟踪满足要求的字符的出现次数(ASCII码值小于256)
        //乱七八糟的字符不包括,计算机中的字符总共是128个,也即是ASCII码,其中33个是无法显示字符,95个是可以显示字符。
        int count[256] = {0};
        while(right<len){
            if(count[s[right]]==0){//新字符
                count[s[right]]++;
                maxlen = max(maxlen, right-left+1); //只有在右边界扩展时才有可能产生新的最大长度
                right++;
            }
            else{//找到重复字符,对左边界进行操作
            	//关键
                count[s[left]]--;
                left++;
            }
        }
        return maxlen;
    }
};

需要想明白:
若字符串为abcdefcg...,则前面部分的最长子串为abcdef(两个c重复),想要找到长度超过这个子串的其它子串,则一定会从第一个c之后开始找。若非如此,则同样会遇到两个c重复的情况,且由于左边界右移,长度只会更小。

想明白之后,另一个思路也随之而来:使用count数组跟踪字符出现的位置

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int left=0, right=0, len=s.length(),maxlen=0;
        int count[256];
        for(int i=0;i<256;i++) count[i] = -1;
        while(right<len){
            if(count[s[right]] == -1 || count[s[right]]<left){//新字符
                count[s[right]]=right;// 记录新字符目前所在位置
                maxlen = max(maxlen, right-left+1);
                right++;
            }
            else{//找到重复字符,对左边界进行操作
                left = count[s[right]]+1;
            }
        }
        return maxlen;
    }
};

但根据提交的结果来看,两者相差不大hhh~
以上方法均是使用数组来辅助判断字符是否已经出现,那么使用set集合来代替则是一个很容易想到的思路:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int left=0, len=s.length(),maxlen=0;
        unordered_set<char> m;
        for(int i=0;i<len;i++){
            while(m.find(s[i]) != m.end()){//出现重复字符
                m.erase(s[left]);
                left++;
            }
            m.insert(s[i]);
            maxlen=max(maxlen, i-left+1);
        }
        return maxlen;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值