leetcode 3090. 每个字符最多出现两次的最长子字符串
题目如下
数据范围
观察数据范围发现s最长也就100也就是说O(n^2)的暴力法的时间复杂度也是可以接受的。
不过本题使用不定长滑动窗口可以优化至O(n)是本人比较推荐的。
那么滑动窗口是如何把时间复杂度优化成O(n)的呢?
暴力法如下
for(int i = 0;i < s.size();i++){
for(int j = i;j < s.size();j++{
.....
}
}
这样写虽然简单但是产生了大量的重复计算即已经知道的合法的子串或者不合法的子串会被多次遍历。而使用滑动窗口。
for(int i = 0;i < n;i++){
while((i + j) < n&&map[s[i + j]] < 2) {
map[s[i + j]]++; j++;
}
max1 = max(max1,j);
j--;
map[s[i]]--;
}
在代码里面我们通过i来固定左端点同时移动j 注意i j都是不走回头路的因为我们保证从i到j的子串是合法的所以没有往回走的必要,换句话说我们只遍历一遍字符串成功把时间复杂度优化到O(n)。
通过代码
class Solution {
public:
int maximumLengthSubstring(string s) {
unordered_map<char,int> map;
int n = s.size();
if(n == 0)return 0;
int max1 = 1;
int j = 0;
for(int i = 0;i < n;i++){
while((i + j) < n&&map[s[i + j]] < 2) {
map[s[i + j]]++; j++;
}
max1 = max(max1,j);
j--;//因为包含s[j]会导致字符串不合法所以实际上我们的i j是左闭右开的
map[s[i]]--;
}
return max1;
}
};