一、题目
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
二、解法
思路:滑动窗口
滑动窗口的本质就是在暴力(双重for循环)下面进行优化,通过维护一个有序的数据结构(比如哈希表),查找和增删的时间复杂度均为O(1),那么可以把时间复杂度降至O(n)
从左往右遍历,遍历变量为 i i i,然后往右查找,只要发现字符没重复,则继续往右查找。怎么判断重复?通过一个哈希集合unordered_set,比如abca,从第一个a开始遍历,往后找到了c停止(第二个a不算)。用一个变量 r t rt rt保存找到的最右边的下标
关键部分:在 i i i遍历的过程中, r t rt rt也一直递增,原因:前一个子串是 i → r t i\rightarrow rt i→rt,后一个子串从 i + 1 i+1 i+1开始,显然 i + 1 → r t i+1\rightarrow rt i+1→rt的部分均是不重复子串,故 r t rt rt是递增的。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int len=s.length();
unordered_set<char> chars;
chars.insert(s[0]);
int right=0,ans=0;
for(int i=0;i<len;++i){
while(right+1<len&&chars.find(s[right+1])==chars.end()){
right++;
chars.insert(s[right]);
}
ans=max(ans,right-i+1);
chars.erase(s[i]);
}
return ans;
}
};