给定一个字符串 s
,请你找出其中不含有重复字符的 最长
子串
的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc"
,所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b"
,所以其长度为 1。
示例 3:
输入: s = "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是"wke"
,所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke"
是一个子序列,不是子串。
思路:
本题使用双指针组成的滑动窗口以及哈希表的map(key表示字符,value表示在字符串中的下标)。l是左指针,r是右指针。
1.开始两个指针都指向首字符,然后r指针开始遍历字符串。
2.在for循环中,如果r指针指向的元素在map中存在(说明字符串之前出现过该字符),并且同时满足l指针的位置小于等于之前字符的位置(即之前的字符在滑动窗口内),那么就让l指针移动到之前字符的下一个位置。
3.把当前r指向的字符及下标,存到map中,并更新最大子串长度。
其实本题的实质就是右指针一直移动,什么时候移动左指针。
在右指针指到重复元素的时候,并且滑动窗口里面还包含之前的重复元素,此时就要把左指针移到之前重复元素的下一个位置。
此时,右指针指向a,发现map表里面有a,即发现了重复元素,但是之前的重复元素a在滑动窗口外,所以不需要移动左指针,把它当成没有重复元素的情况处理即可。
不管左指针是否移动,右指针每次移动后,都要往map表更新,然后更新最大子串长度。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<char, int> map;
int ans = 0;
int l = 0;
for (int r = 0; r < s.size(); r++) {
if (map.find(s[r]) != map.end() && map[s[r]] >= l) {
l = map[s[r]] + 1;
}
map[s[r]] = r;
ans = max(ans, r - l + 1);
}
return ans;
}
};