一、问题描述

二、解题思路
整体思路:
只需要比较以每个位置为首的最长无重复子串的长度就可以得到整体最长无重复子串的长度,模拟这个过程,我们发现可以用双指针法来解决。
经过观察我们可以发现以下两个规律:
(1)固定窗口的左端时,在进窗口的过程中如果发现与前面的字符重复,则无需再进窗口;
若字符串为"abcabcbb",left指向第一个a(已标红),在进窗口的过程中遇到第一个与前面重复的字符a(已标红),则无需再进窗口,以当前left为首的最长无重复字符的子串的长度为3.
(2)出窗口时,right无需回退到left+1的位置,left需要前进到与s[right]重复的字符的后一个位置即可。
若字符串为"a bcabcbb",left指向第一个a(已标红),right指向i=字符a(已标红),当left++后,right无需回退到left+1的位置,只需要保持不变,等待left++,再进行后续操作,因为"bca"是无重复字符的。
详细思路:
(1)定义left,right来维护窗口,数组hash用来记录字符在当前窗口中出现的次数,初始化为0,length用于记录无重复字符的子串的长度;
(2)滑动窗口算法流程:
<1>进窗口
hash[s[right]]++;
<2>判断+出窗口
while(hash[s[right]]>1&&left<=right)
hash[s[left++]]--;
<3>更新长度
length=max(length,right-left+1);
三、代码实现
时间复杂度:T(n)=O(n)
虽然有两重while循环,但是每个元素进窗口一次,出窗口一次,时间复杂度为2n
空间复杂度:S(n)=O(1)
cpp
class Solution {
public:
int lengthOfLongestSubstring(string s) {
//滑动窗口
int left=0,right=0,n=s.size();
int hash[128]={0};
int length=0;
while(right!=n){
//进窗口
hash[s[right]]++;
//判断
while(hash[s[right]]>1&&left<=right)
hash[s[left++]]--;
//更新
length=max(length,right-left+1);
right++;
}
return length;
}
};