面试题48:最长不含重复字符的子字符串

目录

1.动态规划

2.滑动数组

1.动态规划

先来分析一下吧。。。这题我们很容易想到,假设f(i)表示以下标i结尾的s[i]中的最长不含重复字符的子字符串,那么f(i)=f(i-1)+1是不是很容易想到?不过这里是有条件的,首先,i\geqslant 1,其次,这里面如果以s[i-1]结尾的字符串里包含s[i]的字符怎么办?我们是不是要取上次出现的相同s[i]到当前位置i的距离作为f(i)。

以下是代码:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int len=s.size();
        if(len==0) return 0;
        int position[128];//通过ascii码作为索引可以访问上一次出现的位置
        for(int &i:position) i=-1;
        int curLength=0,ans=0;
        for(int i=0;i<len;++i)
        {
            //记录上一次的相同字母的位置
            int index=position[s[i]];
            //直接对curLength增一操作有两种情况
            //1.第一次出现
            //2.和上一次出现的相同字母之间的距离大于以i-1个字母结尾的最长长度
            if(index==-1||i-index>curLength)
            {
                ++curLength;
            }
            else
            {
                //每次等到要直接切换curLength的时候更新ans
                if(curLength>ans)
                {
                    ans=curLength;
                }
                curLength=i-index;
            }
            position[s[i]]=i;
        }
        //可能最后一次记录的curLength没有更新
        if(curLength>ans)
        {
            ans=curLength;
        }
        return ans;
    }
};

这里用position数组来实现了记录上一次出现位置的功能,即字符到位置的映射。

不过说这题是不是不大严谨,我都不知道他字符的范围一开始......

2.滑动数组

学习一下嘿嘿,直接cv:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int l=0,r,maxLen = 0;
        int a[128];
       //记录字符上一次出现的位置
        for(int &i:a){i =-1;}
        for(r = 0;r<s.length();){
            //上一次出现的位置在窗口外或者没有上次出现
            if(a[s[r]]==-1 || a[s[r]]<l){
                a[s[r]] = r;
                r++;
            }else{
                //出现重复,移动窗口
                 maxLen = max(maxLen,r-l);
                 l = a[s[r]]+1;
                 a[s[r]] = r;
                 r++;
            }
        }
        maxLen = max(maxLen,r-l);
        return maxLen;
    }
};

感觉大同小异吧,只是解释的方法不一样,感谢大佬教我编程~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值