1.无重复字符的最长字串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
这题的最优解法是滑动窗口,一开始我是一直保持窗口只会增大不会增小,具体做法是一次遍历,每次检查数组是否存在大于一的,代表有重复的字符串,滑动窗口平移,当不存在重复字符串时,滑动窗口向右增大,这种做法开销在于检查数组,所以还挺耗时的。
优化的做法为一次遍历,将i一直作为滑动窗口的右窗口,最大值为遍历的最大的窗口大小,每次遍历时,左窗口为max(l,v[s[i]]),当窗口中没有重复的数字时,v[s[i]]是0或者一个比l小的值,当有重复的数字时,跳到窗口内第一个不存在重复字符的地方,改变右窗口的字符所在的数组的值,该值为右窗口+1,左窗口根据这个值移动。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if(s.empty())return 0;
vector<int> v(128, 0);
int l = 0;
v[s[0]] = 1;
int ret = 1;
for(int i = 1; i < s.size(); i++){
l = max(l, v[s[i]]);
ret = max(ret, i-l+1);
v[s[i]] = i+1;
}
return ret;
}
};
2.字符串出现的最大次数
给你一个字符串 s ,请你返回满足以下条件且出现次数最大的 任意 子串的出现次数:
子串中不同字母的数目必须小于等于 maxLetters 。
子串的长度必须大于等于 minSize 且小于等于 maxSize 。
示例 1:
输入:s = "aababcaab", maxLetters = 2, minSize = 3, maxSize = 4
输出:2
解释:子串 "aab" 在原字符串中出现了 2 次。
它满足所有的要求:2 个不同的字母,长度为 3 (在 minSize 和 maxSize 范围内)。
示例 2:
输入:s = "aaaa", maxLetters = 1, minSize = 3, maxSize = 3
输出:2
解释:子串 "aaa" 在原字符串中出现了 2 次,且它们有重叠部分。
示例 3:
输入:s = "aabcabcab", maxLetters = 2, minSize = 2, maxSize = 3
输出:3
示例 4:
输入:s = "abcde", maxLetters = 2, minSize = 3, maxSize = 3
输出:0
提示:
1 <= s.length <= 10^5
1 <= maxLetters <= 26
1 <= minSize <= maxSize <= min(26, s.length)
s 只包含小写英文字母。
这道题的基本方法是用滑动窗口,我们可以分析出窗口的大小只与minSize有关,而与maxSize无关,滑动窗口固定后就方便解决了。我在解这道题的时候出现了错误,一开始我使用了string的find函数来统计每个字串的个数,可这样做效率太低,时间复杂度非常大,然后我用一个备忘录来记录是否有相同的字串已经被记录过,结果发现依然超时。。。其实只需要以空间换时间的方法,用哈希表保存每个字串,value为字串的个数即可。。。
总结:字符串问题大部分遍历可以用哈希表来优化时间,如two sum问题,一定不要死脑筋。
class Solution {
public:
int maxFreq(string s, int maxLetters, int minSize, int maxSize) {
unordered_map<char, int> m;
unordered_map<string, int> h;
int l = 0;
int max_ = 0;
for(int r = 0; r < s.size(); r++){
m[s[r]]++;
if(r-l+1 < minSize){
continue;
}
if(m.size() > maxLetters){
m[s[l]]--;
if(m[s[l]] == 0)
m.erase(s[l]);
l++;
continue;
}
string temp = s.substr(l, r-l+1);
h[temp]++;
m[s[l]]--;
if(m[s[l]] == 0)
m.erase(s[l]);
l++;
}
for(auto &n:h){
max_ = max(max_, n.second);
}
return max_;
}
};