Problem: 3. 无重复字符的最长子串
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
思路
- 滑动窗口遍历字符串
- 哈希表记录字符种类和位置
解题方法
使用两个int类型来记录无重复字符的最左边(left)和最右边(right)
如上图中2,right移动到这里时,查哈希表时发现有重复字符,停下:
(1)计算这一次不重复字符子串长度,如果比原纪录最长子串长度长则替换
(2)哈希表中查到该重复字符原位置,left跳到该位置的下一个位置作为新的left位置,如下图:
ps:这个时候应该要清除哈希表中,排在在字符串s中新left前面的所有记录。但是出于性能方面的考虑,我直接使用下面代码:
(r.find(m)->second)<left
让程序在查找哈希表时进行忽略
复杂度
- 时间复杂度:
O ( n ) O(n) O(n)
- 空间复杂度:
O ( n ) O(n) O(n)
Code
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<int, int> r;
if (s.empty()) {
return 0;
}
int left = 0;
int right = 0;
int size = 0; //记录本次长度
int maxSize = 0; //记录最大长度
while (right < s.size()) {
int m = s[right]-' ';
//下面这个while用来定位right的新位置,
// 如果当前right所对应的字符在哈希表没有;
// 或者在哈希表中查到在s中的位置在left之前,right都可以往后走
while ( r.find(m) == r.end()||r.find(m)->second<left) {
r[m] = right;
++right;
if (right == s.size()) break;
m = s[right]-' ';
}
size = right - left;
maxSize = (size > maxSize) ? size : maxSize;
//定位left的新位置
left = r[m]+1;
//哈希表中right对应的字符位置更改为当前right位置
r[m] = right;
right++;
}
return maxSize;}
};