原题链接:Leetcode 3. 无重复字符的最长子串
这道题之前写过一次:Leetcode 3. 无重复字符的最长子串 滑动窗口,怎么说呢,自己都看不懂的程度
现在是2024.8.16重做这道题
解法1: 使用左右指针,左指针先定住,右指针向右滑动,窗口内的字符串表示无重复字符的字符串,每个字符用一个map
容器标记是否已经出现过,如果出现过,标记mp[s[r]]=1,如果当前右指针处的字符已经出现过了,那么将左指针右移,直到重复字符第一次出现处的后一个位置,移动过程中将所有字符在map容器中的状态清空。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int res = 0;
int l = 0, r = 0;
map<char, int> mp;
while (l <= r && r < s.size()) {
if (!mp[s[r]]) {
mp[s[r++]] = 1;
res = max(res, r - l);
} else {
while (s[l] != s[r]) {
mp[s[l]] = 0;
l++;
}
mp[s[l]] = 0;
l++;
}
}
return res;
}
};
解法二: 将解法一中记录某个字符是否出现过(mp[ch]=1)
,改过记录它上一次出现的位置(mp[ch]=i+1)
,以此取消左指针的右向逐步移动,而是直接将左指针定位到重复元素上一次出现的位置mp[ch]
的下一个位置,这样改变之后,if (mp[s[i]] && mp[s[i]] < l)
是灵魂。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int res = 0;
int l = 0, r = 0;
map<char, int> mp;
for (int i = 0; i < s.size(); i++) {
if (!mp[s[i]] || (mp[s[i]] && mp[s[i]] < l)) {
mp[s[i]] = i + 1;
res = max(res, i - l + 1);
} else {
l = mp[s[i]];
mp[s[i]] = i + 1;
}
}
return res;
}
};