给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串的长度。
示例 1:
输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是"abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是"b",所以其长度为 1。
提示:
0 <= s.length <= 5 * 10^4
s
由英文字母、数字、符号和空格组成
利用可变长的滑动窗口,初始化start,end指向初始位置。使用hashmap记录某字符最后一次出现的下标,目的是当它再次出现时,可以直接滑动start到重复字符的下一位。
以end作为遍历指针,发现新字符a,加入map中。
加入字符b。
此时遇到了重复字符a,按照上面提到的,利用map存储的下标,直接将start滑到已记录的a的下一位。
这里可以发现map中的{c,0}其实已经不在这步中的子串中了,但我们无需对他进行操作,只需要进行一个判断:字符对应的value值和当前start的大小,如果value更小,说明当前滑动窗口不包含对应的存储字符。
遇到重复字符a,滑动start、end,更新map。
接下来碰到“重复”字符c,注意这里是假重复,按照上面所说,map中存储的c的下标小于了start,实际上是没有c的。
向map添加新字符。
遇到重复字符a,移动start到a的下一位。
遇到重复字符c,移动start到c的下一位,同时end到了字符串末尾,遍历结束,输出过程中子串最长的大小。
代码:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int max_count = 0;
int start = 0;
std::unordered_map<char, int> map;
for (int end = 0; end < s.length(); end++) {
char c = s[end];
if (map.find(c) != map.end() && map[c] >= start) {
start = map[c] + 1;
}
map[c] = end;
max_count = std::max(max_count, end - start + 1);
}
return max_count;
}
};