题目来源
题目描述
class Solution {
public:
int characterReplacement(string s, int k) {
}
};
题目解析
思考
- 如果没有k的限制,让我们求把字符串变成只有一个字符重复的字符串需要的最小置换次数,那么就是字符串的总长度 - 出现次数最多的字符的个数
- 如果加上k的限制,那么就是求满足[子字符串的长度- 出现次数最多的字符个数 <= k的最长字符串]
- 因此,我们需要在滑动窗口的范围内,统计各个字母的数字,并保留出现次数最多字母的个数
- 什么时候窗口缩小呢?当[ 当前窗口大小 - 窗口中出现次数最多的字符个数] > k时,窗口缩小
- 为啥这里不用更新 maxCnt 呢?
- 原因是此题让求的是最长的重复子串,maxCnt 相当于卡了一个窗口大小,我们并不希望窗口变小,虽然窗口在滑动,但是之前是出现过跟窗口大小相同的符合题意的子串,缩小窗口没有意义,并不会使结果 res 变大,所以我们才不更新 maxCnt 的
- 虽然这样的操作会导致部分区间不符合条件,即该区间内非最长重复字符超过了 kk 个。但是这样的区间也同样不可能对答案产生贡献。当我们右指针移动到尽头,左右指针对应的区间的长度必然对应一个长度最大的符合条件的区间。
class Solution {
public:
int characterReplacement(string s, int k) {
std::vector<int> counts(26, 0);
int left = 0, res = 0, maxCount = 0;
for (int i = 0; i < s.size(); ++i) {
counts[s[i] - 'A']++;
maxCount = std::max(maxCount, counts[s[i] - 'A']);
// 若当前窗口大小 减去 窗口中最多相同字符的个数 大于 k 时
while (i - left + 1 - maxCount > k){
counts[s[left] - 'A']--;
left++;
}
res = std::max(res, i - left + 1);
}
return res;
}
};