解法1:滑动窗口
思想:
用set维护一个不重复的滑动窗口,得到以s[right]为结尾的最长无重复子串(即s[left]到s[right])。
复杂度:
●时间:O(N),for循环需遍历n次,while循环只有重复才执行,就算最坏情况下全部重复也就执行N次,所以O(N) + O(N)
●空间:O(1),set中最多存储128个数。使用vector效率更高。
代码:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int res = 0;
unordered_set<char>my_set;
for(int left = 0, right = 0; right < s.size(); right++){
//如果s[right]重复了,就从left开始弹出(left++),直到不重复
while(my_set.find(s[right]) != my_set.end())
my_set.erase(s[left++]);
//插入当前s[right]字符
my_set.insert(s[right]);
//因为当前只是以s[right]结尾的最长子串,所以每轮需要更新一下
res = max(res, right - left + 1);
//res = max(res, int(my_set.size())); 用set.size()更好理解一点,因为里面都是不重复的
}
return res;
}
};
改进:
思想:关于字符的set都可以用vector来代替,这样可以提高效率。
注意:可以用vec_exist[s[right]]来直接访问数组,即ASCII码为index直接访问
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if(s.size() <= 1)
return s.size();
int res = 0;
//注意题目说的是字符,不是字母,所以要128个
vector<int>vec_exist(128, 0);
for(int left = 0, right = 0; right < s.size(); right++){
while(vec_exist[s[right]] > 0)
vec_exist[s[left++]] = 0;
vec_exist[s[right]] = 1;
res = max(res, right - left + 1);
}
return res;
}
};