给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次。在执行上述操作后,找到包含重复字母的最长子串的长度。
注意:字符串长度 和 k 不会超过 10^4。
示例 1:
输入:s = "ABAB", k = 2
输出:4
解释:用两个'A'替换为两个'B',反之亦然。
这是一个用滑动窗口做的典型题目,因为之前没怎么接触过,所以根据题解,学习一下关于滑动窗口的知识点。
可以分为三步:
1.窗口初始宽度为1
2.出现更长的满足要求序列,宽度+1
3.当前没有满足要求的更长的序列,整个窗口平移
窗口扩张:left 不变,right++
窗口滑动:left++,right++
这个题的关键点就是判断改变一个字符串中的K个字符 ,使能够变成一个连续串
如果当前字符串中的出现次数最多的字母个数 +K 大于串长度,那么这个串就是满足条件的
我们维护一个数组 int[26] 来存储当前窗口中各个字母的出现次数,left 表示窗口的左边界,right 表示窗口右边界
窗口扩张:left 不变,right++
窗口滑动:left++,right++
historyCharMax 保存滑动窗口内相同字母出现次数的历史最大值,通过判断窗口宽度 (right−left+1) 是否大于 historyCharMax + K来决定窗口是否做滑动,否则窗口就扩张。
最后返回窗口长度。
class Solution {
private int[] map = new int[26];
public int characterReplacement(String s, int k) {
char[] chars = s.toCharArray();//字符串转字符数组
int n = chars.length;
int left =0;
int right=0;
int historyCharMax = 0;
for(right=0; right<n;right++){//ABAB
int index = chars[right] -'A';//chars[right]是A,index是65-65=0,因此A是0,B是1,C是2,以此类推
map[index]++;//字母计数
historyCharMax = Math.max(historyCharMax,map[index]);//historyCharMax 保存滑动窗口内相同字母出现次数的历史最大值
if(right - left + 1 > historyCharMax + k){//窗口是否滑动的判断条件
int index_left = chars[left] - 'A';//窗口左边界的编号
map[index_left]--;//由于向右滑动,左边界的字母在窗口之外了,所以次数减1
left++;
}
}
return n-left;
}
}