题目分析
给你一个 仅由大写英文字母组成 的字符串,你可以将任意位置上的字符替换成另外的字符,总共可 最多替换 k 次 。在执行上述操作后,找到包含 重复字母的最长子串的长度 。
注意:字符串长度 和 k 不会超过 10^4。
力扣:424. 替换后的最长重复字符
s = “ABABBCCCCDC” k = 2
max_len = 7
题目分析
此题和 力扣:1004. 最大连续 1 的个数 III 看似相同,又有所不同,但本质都是 滑动窗口 ,因为求的都是连续的最长子序列。不同点在于,最大连续 1 的个 数中数字串只包含 0 和 1 两种元素,因此只需要记录滑动窗口中 0 的个数与给定 k 关系;
本题中,字符不止 2 种, 那么考虑将那个字符作为 最长子串的基串 确实有一定的难度。
可能有的 ACMer 会想到,求出最长连续的字符的长度 len ,然后将 len + k 理解成本题的解,反例其实很好找
s = "BBBAACAACAA" k = 2
回到本题中,其实只需要求出窗口中出现次数最大的字符 maxn
,随后只需要保持该窗口的大小继续向右扩展,大小为 maxn + k
, 直到窗口中出现下一个最大出现的字符, 更新 maxn
,这样就可以 始终维持一个最大的窗口 (长度为 maxn + k) 向右直到字符串遍历完,最终的长度就是 right - left
。
字符的最大次数可以用一个长度为 26 的数组维护即可。
class Solution {
public int characterReplacement(String s, int k) {
int[] count = new int[26];
int maxn = -1; // 用来记录 0 - right 之间出现次数最大的字符
int left = 0 , right = 0;
int len = s.length();
while(right < len){
char ch = s.charAt(right);
count[ch - 'A'] ++;
maxn = Math.max(maxn , count[ch - 'A']);
if(right - left + 1 - maxn > k){
count[s.charAt(left) - 'A'] --;
left ++;
}
right ++;
}
return right - left;
}
}