力扣 T3. 无重复字符的最长子串

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

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

请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

最简单的想法:直接遍历整个字符串,判断当前字符是否出现过。没有出现,最长子串长+1;出现过,向前找到该字符,下一次从该字符的后一个位置开始遍历,重置长度为1.

时间复杂度为O(n),空间复杂度O(1);

但是如果字符串S由很长的无重复字串循环组成,如:”abcabcabc“。此时每次都要向前回溯最长子串长,导致算法的效率很低。因此,可以对这一回溯过程进行优化。即用空间换时间,多记录每个字符第一次出现的位置,避免用循环的方法回溯,而是直接找到上一次该字符出现的位置进行下一次遍历。有点类似于KMP。

不妨设当前的最长无重复字串的左端点对应字符为”L“,第一次出现的位置为”Pl“;右端点对应字符为”R“,第一次出现的位置为”Pr“。

从字符串首开始遍历,对于当前遍历到的字符S[i],判断是否重复出现过:

若第一次出现,记录下该字符曾经出现过,以及出现的位置,最长子串长度+1;

若原来出现过,将左端点L移动到该字符第一次出现位置的后一位(此处设为P+1,即第一次出现的位置为P),右端点移动到当前位置 i,并把从原来的L开始,到P这段子串中,所有出现过的字符的出现次数全部标记为0,更新目前的最长字串(目前找到的,不一定是结果)长度为i-p.

如此遍历整个字符串,就可以得到不含重复字符的最长字串长。

int lengthOfLongestSubstring(char * s){
    int t=0,ans=0,maxn=0;
    int num[260]={},pos[260]={};//num用于记录字符,pos记录对应字符第一次出现的位置
    while(s[t]!='\0')
        t++;
    if(t==0)return 0;

    for(int i=0;i<t;i++)
    {
        num[s[i]]++;
        if(num[s[i]]>1)    //如果某字符重复出现了
        {
            if(ans>maxn)maxn=ans;//更新最长子串

            int temp=i-ans;    //重复字符前有多少个字符,比如“abcb”,需要将a的出现次数重置为0
            for(int j=pos[s[i]]-1;j>=temp;j--)
                num[s[j]]=0,pos[s[j]]=0;
            num[s[i]]=1;ans=i-pos[s[i]]-1;    //更新当前的最长子串长
        }
        pos[s[i]]=i;ans++;//统一在循环时ans+1,因此上面的ans需要-1
    }
    if(ans>maxn)maxn=ans;
    return maxn;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值