LeetCode-3 无重复字符的最长子串 Longest Substring Without Repeating Characters

题目

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

示例 1:

输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:

输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:

输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

思路

我知道,对某个问题想出最佳解法固然难得,然而要将自己的想法解释给他人听懂则更为难得。

对于这个问题,可以使用滑动窗口的方法来解决。
可以将字符串视为一条铁轨,而滑动窗口则是铁轨上的一辆列车。列车的长度可以伸缩,每节列车对应铁轨上的一个字符。

  1. 首先固定列车的尾部,将列车的头部向前延伸,每延伸一节,就查看新加的这一节对应的铁轨上的字符是否在列车中出现过,没出现过则继续延伸。
  2. 如果出现过,则将列车的长度-1就是到当前位置最大的无重复子串长度,记为maxlen。
  3. 固定列车的头部,将列车的尾部向前延伸,即缩短列车的长度,直到重复的情况消除。
  4. 重复步骤2-3,比较每次的maxlen,取较大者。直到列车头部到达铁轨终点,再取一次maxlen比较。

写代码

对于上述思路,在写代码的过程中可以进一步优化。思路在于,当出现重复时,我们将列车尾部逐渐前移,直到重复消除,如果能使尾部直接移到重复位置的下一个位置,则可以大大节约时间。

  1. 考虑使用一个hash-map,int m[128], 记录每个字符上一次出现的位置。并记录列车尾部的位置last.
  2. 列车头部前进时,每遇到一个字符c,就检查它上一次出现的位置m[c],如果m[c]>=last,则说明此字符在列车中出现过,更新maxlen,将l移至m[c]+1的位置,并更新m[c]为列车头部位置。
  3. 重复步骤2,直到字符串结尾,再更新一次maxlen。

附代码

/*
思路:记录子串的开头和结尾下标,并记录子串中每个字符的下标。
将结尾位置后移,如果新加入的字符上一次出现的下标大于开头,则说明此字符重复
将当前子串大小-1,并与result比较,取较大者
将开头移到上一次出现此字符的位置之后一位
继续后移结尾
*/
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int result=0;
        vector<int> m(128,-1);//用于记录每个字符上一次出现的位置的下标
        
        int size=s.size();
        int f=0;//子串开头
        int l=0;//子串结尾
        
        //将l后移直到出现重复
        while(l!=size)
        {
            if(m[s[l]]<f) m[s[l]]=l;//如果s[l]上一次出现的位置小于f,说明在当前子串中s[l]不重复
            
            else//出现了重复,就把f向后移到消除重复的位置
            {
                //在此处更新一下result,f到l-1是不重复的
                result=max(result,l-f);
                
                f=m[s[l]]+1;
                m[s[l]]=l;
            }
            
            ++l;//后移l
        }
        
        //l到结尾退出,再更新一下result
        result=max(result,l-f);
        
        return result;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值