【leetcode】无重复字符的最长子串【C++】

版权声明:本文为博主原创文章,未经博主允许不得转载 https://blog.csdn.net/qq_34018840/article/details/89176811

题目如下:

解题思路:

对于例子"abcabcbb",手动找无重复字符的子串该怎么找?单个字符遍历a、b、c;然后又出现了一个a,此时应该去掉第一次出现的a;继续往后又出现了一个b,则应该去掉一次出现的b,以此类推最终发现最长长度为3。手动推导的方法实际上是维护了一个无重复字符的滑动窗口。由于窗口在不停向右滑动,所以只关心每个字符最后出现的位置,并建立映射。字符出现的位置可以使用HashMap来建立字符和其出现位置之间的映射。同时还需要维护一个值用于记录最大长度。

本题的思路就是利用滑动窗口 + hash表来解决问题,i 为当前窗口的右边界,left 为当前窗口左边界,res 用于记录最大窗口值。对于访问过的元素就在hash表中存储其最新的位置值,当每一次右移滑动窗口右边界 i 时,判断其对应的元素hash表中是否已经出现过:

  • 如果没有出现过,那么直接更新当前窗口大小 res,同时继续右移滑动窗口右边界 i 即可
  • 如果出现过但是其位置在 left 左边,那么就说明与当前数组元素重复的元素在之前已经被移出了滑动窗口,那么直接更新当前窗口大小 res,同时继续右移滑动窗口右边界 i 即可;
  • 如果出现过但是其位置在 left 右边,那么就说明与当前数组元素重复的元素在滑动窗口内,需要更新滑动窗口左边界,之后右移滑动窗口右边界 i

代码如下(C++):

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int res = 0, left = 0, ls = s.size();
        map<char,int> mapLS; //建立hash表
        for(int i = 0; i < ls; ++i){
            if(mapLS[s[i]] == 0 || mapLS[s[i]] < left){ 
            //当前元素未出现过,或者出现过但是其位置在left标志的左边
                res = max(res, i - left + 1); //更新最长子串大小
            }
            else{
                left =  mapLS[s[i]]; //更新滑动窗口左边标记值
            }
            mapLS[s[i]] = i + 1; //出现过的元素就加入hash表中,且保存最新的元素位置
        }
        return res;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_34018840/article/details/89176811