3. 无重复字符的最长子串 - 力扣(LeetCode) (leetcode-cn.com)
设置两个指针l,r。l和r分别指向子串的首尾元素。l从0开始且基于l进行for循环,r从-1开始且在for循环中利用while对r进行遍历。
注意:l移动后说明l-1已经退出窗口了,因此要在set中清除l-1;while循环中遍历的实际上是r+1,这样当r+1为重复元素时,保存的r即为符合要求的窗口右边界
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_set<char> hash;
int r = -1; //右指针,初始在字符串边界之外
int ans = 0;
for(int l = 0; l < s.size(); l++) { //l为左指针
//左指针左移后要更新hash
if(l != 0)
hash.erase(s[l-1]);
//右指针移动
while(r + 1 < s.size() && !hash.count(s[r+1])) {
hash.insert(s[r+1]);
++r;
}
//子串从l到r
ans = max(ans, r - l + 1);
}
return ans;
}
};
424. 替换后的最长重复字符 - 力扣(LeetCode) (leetcode-cn.com)
本题要求一个最长重复字符串,该串可通过对某一子串修改最多k次得到。误区是真的用k次来替换字符。实际上可以得到判断当前子串是否符合要求的条件:当前子串长度(即子串中所有字符的出现次数和) - 子串中出现次数最多的字符的出现次数 <= k。也就是说当~ - ~ > k时,就该调整子串范围了。
滑动窗口的原理:l和r指针,r负责向右扩展,遍历新字符;当不符合要求时,l右移。
注意:和上一题一样,l右移前一定要更新状态,本题是l对应的字符出现次数-1然后l再右移。
class Solution {
public:
int characterReplacement(string s, int k) {
vector<int> nums(26, 0);
int l = 0, r;
int maxNum = 0; //用于记录当前出现次数最多的字符的出现次数
for(r = 0; r < s.size(); r++) { //右指针用于扩展,遍历新的字符
++nums[s[r] - 'A']; //遍历到的字符,记录更新
maxNum = max(maxNum, nums[s[r]-'A']); //比较刚刚遍历到的字符是否出现次数是最多的
//如果当前子串不能通过k次修改来达到全体字符相同,则左指针移动
if((r - l + 1) - maxNum > k) {
--nums[s[l]-'A'];
++l;
}
}
return r - l;
}
};