无重复子串

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

  • 0 <= s.length <= 5 * 104
  • s 由英文字母、数字、符号和空格组成

这道题最先想到的是哈希表与滑动窗口,当然你用两层循环肯定没有错,但是时间复杂度会很高。

看题我们知道s最大长度应该是95(参照anscii表,把不在上述范围内的给去掉)

我们可以设置一个长度为127的数组来存储字符的映射(参照anscii表的映射)

对于哈希表与滑动窗口,肯定需要用到双指针,left和right

那么这两个指针都做了什么工作呢?

right指针用来第一次便利,并且将扫描到的字符的映射数组的值改为1作为标记,直到扫描到映射数组值为1,那么当前已经扫描到了第一个无重复的子串了,等待left做接下来的工作。

left指针用来将right前边的所有映射清0,并记录新的窗口的起始点,left和right从新的起始点开始工作。

让我们来看一下这个代码

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        //哈希表的映射加滑动窗口
        if (s[0]=='\0')
            return 0;
        int mapping[127]={0};
        int left = 0;
        int right = 0;
        int count = 0;
        int max = 0;
        int temp=0; //记录新的窗口起始点
        while (s[right]!='\0'){
            if(mapping[int(s[right])] == 0){    //把当前出现的字符对应的位置的数据增加
                mapping[int(s[right])]=1;
                count++;
                right++;
            }
            else{
                if(count>max){
                    max = count;
                }
                if (max>=95)                //最大值是95,遇到95就退出
                    return 95;
                if(left!=right){           //把前边的映射数组清空
                    if(s[left]==s[right])
                        temp = left+1;      //找到新的滑动窗口起始点并记录
                    else mapping[int(s[left])]=0;
                    left++;
                }
                else {mapping[int(s[temp-1])]=0;left = right = temp;}
                count =0;
            }
        }
        if(count>max)
            return count;
        return max;
    }
};

但是上述代码仍有优化的空间

“left指针用来将right前边的所有映射清0,并记录新的窗口的起始点,left和right从新的起始点开始工作。”

这个思路固然没错,但是,我们把right前,新的起始点后的映射数组清零再重新计数做了一遍重复的工作,所以我们可以让left把新的起始点之前的映射数组给清零,然后再让right继续前进。可以节省很多重复性的工作

class Solution {
public:
    int res = 0;
    int p[1000];
    int lengthOfLongestSubstring(string s) {
        p[s[0]] ++;
        for(int i = 0,j = 0;i < s.size();)
        {
            while(p[s[j]] == 1 && j < s.size()) 
            {
                j ++;
                p[s[j]] ++;
            }
            res = max(res,j - i);
            p[s[i]] --;
            i ++;
        }
        return res;
    }
};

上述代码看似是两重循环,其实比第一个代码效率更高。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值