题目
给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次。在执行上述操作后,找到包含重复字母的最长子串的长度。
注意:字符串长度 和 k 不会超过 104。
示例1
输入:s = "ABAB", k = 2
输出:4
解释:用两个'A'替换为两个'B',反之亦然
示例2
输入:s = "AABABBA", k = 1
输出:4
解释:
将中间的一个'A'替换为'B',字符串变为 "AABBBBA"。
子串 "BBBB" 有最长重复字母, 答案为 4。
题解
- 对于一个子串
如:ABAB
,其内部字符包含A和B,我们找到该子串内部出现次数最多的字符A或者B
,最大次数maxCount
为2,由于有k个字符可以被替换。即当该子串长度 <= maxCount+k时,代表该子串可以表示为一个含有重复字母的子串 - 找到该子串内部某一字符出现的最多次数
maxCount
,因为有k次的容错机会,所以这k次机会都要给已经出现次数最多的字符- 当该子串长度
right-left+1
<maxCount+k
:表示此时该k还有剩余,即可以继续增加最长子串的长度,即右指针右移 - 当该子串长度
right-left+1
>maxCount+k
:此时k显得“力不从心”不能替换不同的字符了;此时需要更新左指针
- 当该子串长度
参考代码
class Solution {
public int characterReplacement(String s, int k) {
int left = 0, right = 0;
int maxCount = 0;
int res = 0;
Map<Character, Integer> map = new HashMap<>();
while(right < s.length()) {
char key = s.charAt(right++);
int val = map.getOrDefault(key, 0);
map.put(key, val+1);
maxCount = Math.max(maxCount, map.get(key));
if(right - left > maxCount + k) {
int a = s.charAt(left++);
map.put(a, map.get(a)-1);
}
res = Math.max(res, right - left);
}
return res;
}
}