最长无重复字串

Posted 一个山里的少年

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最长无重复字串相关的知识,希望对你有一定的参考价值。

对应letecode链接:

力扣

题目描述:

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

示例 1:

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

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

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

输入: s = ""
输出: 0

提示:

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

 解题思路:

我们利用i,j指针持续维护我们的“窗口”,我们保证窗口内不含有重复字符。循环开始时,j=i+1。循环中,j不断前移,窗口的长度“变长”,而i则根据窗口内是否有重复字符而控制窗口的长度。滑动窗口本质上就是一种枚举方式,枚举对于i的各种取值,子串所能取到的最大长度,但是这种枚举前后有相关性,因为我们只用考虑窗口元素的“进去”,大大减少了枚举次数。

 j指针开始往后移动一直到出现重复字符或者到了字符串的长度就停止移动

 

此时无重复字串的长度为j-i也就是3下一次i就从b开始

j指针开始移动

  

此时无重复字符的字串长度依然为j-i也就是3然后i在加加再次往后重复上述步骤在遍历的过程中我们只需要定义一个遍历maxlen记录最大无 重复字符字串的长度即可

 那么我们如何判断是否重复呢?我们只需要使用一个哈希表记录即可,在下一次遍历之前将其清空即可

对应代码:

class Solution 
public:
    int lengthOfLongestSubstring(string s) 
            int n=s.size();
               int maxLen=0;//记录最长出现的字符
            unordered_set<char>tmp;//保存出现的字符
            for(int i=0;i<n;i++)
                  tmp.insert(s[i]);
                  int j=0;
             for(j=i+1;j<n;j++)
                 if(tmp.count(s[j]))//如果已经出现重复的直接跳出程序
                     break;
                 else
                      tmp.insert(s[j]);//没有重复则继续插入
                 
             
             //记录最大无重复字串的长度
             if(j-i>maxLen)
                 maxLen=j-i;
             
             tmp.clear();//清空容器

            
            return maxLen;
    
;

但是这样的时间复杂度是0(N^2) 有没有时间复杂度为O(N)的方法呢?我们可以使用一个数组记录字符出现的位置

假如我们有这们一个字串串我要求以a结尾无重复字串的长度我们只需要看此时看i减去i下标对应的字符上次出现的位置和对应以i-1对应字符结尾的无重复字符的长度+1两者取最小值即可。可能有老铁不太明白是什么意思马上就解释

 

这个字符串如果我们要求 以i下标对应字符结尾的最大无重复字符的长度我们首先看i下标对应的字符为a他上次出现的位置为1号位置i为4而以i-1下对应字符结尾的最大无重复字串的长度为4但是先加入的a已经在对应已i-1下标结尾的最大无重复字串中出现过了所以以i位置结尾的最大无重复字符的字串的长度为4-1=3;也就是两者取最小值

我们再来看这一种情况:

 

我们可以发现i上次出现的位置为0号位置i为4号位置而已i-1对应字符结尾的最大无重复字符的字串长度为2为什么不能够更长了只有可能是出现了重复字符此时i-0=4-0=4而以i-1下标对应字符结尾的最大无重复字串的长度+1为3两者取最小值即为3也就是以i下标对应字符结尾的最大无重复字符字串的最大长度。在上述过程中我们只需要定义一个变量maxLen记录整个 字符串中最长无重复字符字串的最大长度即可

对应代码:

class Solution 
public:
    int lengthOfLongestSubstring(string s) 
                 if(s.size()==0)
                     return 0;
                 
                int arr[256]=0;
                for(int i=0;i<256;i++)//没有开始之前全部填成-1;
                    arr[i]=-1;
                

               arr[s[0]]=0;//第一个字符无重复字符字串的长度为0
             int preMaxlen=1;//对应以i-1对应字符结尾无重复字符字串的长度
             int MaxLen=1;//记录最大长度
             for(int i=1;i<s.size();i++)
                preMaxlen=min(i-arr[s[i]],preMaxlen+1);
                if(preMaxlen>MaxLen)
                    MaxLen=preMaxlen;
                
                arr[s[i]]=i;
             
             return MaxLen;
    
;

 

以上是关于最长无重复字串的主要内容,如果未能解决你的问题,请参考以下文章

最长无重复字串

最长无重复字串

leetcode第三题 无重复的最长字串

leetcode算法-中等3. 无重复字符的最长字串

《LeetCode之每日一题》:78.无重复字符的最长字串

无重复字符的最长字串