题目
给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次。在执行上述操作后,找到包含重复字母的最长子串的长度。
注意:字符串长度 和 k 不会超过 104。
示例 1:
输入:s = "ABAB", k = 2 输出:4 解释:用两个'A'替换为两个'B',反之亦然。
滑动窗口
public class Main {
public static void main(String[] args) {
Main main = new Main();
main.characterReplacement("AABABBA", 1);
}
public int characterReplacement(String s, int k) {
// charAppearTimes记录在滑动窗口内不同字符出现的次数
int [] charAppearTimes = new int [26];
// 需要保存滑动窗口内 出现过的某个字母的历史最大值
int windowMaxTimes = 0;
int left = 0;
int right = 0;
while (right < s.length()) {
char temp = s.charAt(right);
// A的ASCII码是65, 减去A是将所有的大写字符平移到0-26
charAppearTimes[temp - 'A'] += 1;
windowMaxTimes = Math.max(charAppearTimes[temp - 'A'], windowMaxTimes);
// 如果windowMaxTimes + k > right - left + 1 就说明窗口可以尝试扩大
if (windowMaxTimes + k >= right - left + 1) {
right++;
continue;
}
// 窗口长度不变, 进行滑动, 移除滑出去的元素, 左右指针均+1
charAppearTimes[s.charAt(left) - 'A'] -= 1;
left ++;
right++;
}
return right - left;
}
}
基本思路
-
题目可以理解为在一个长度为l的窗口内, 如果该窗口内的重复字母为n个, 那么如果n + k >= l, 就说明该窗口的长度就是这段字符串替换后的最长重复字符串, 因此可以尝试扩大窗口, 继续判断是否符合n + k >= l的条件.
-
用一个26长度的数字来记录窗口内每种字符出现的次数, 注意需要对ASCII码进行偏移, 例如charAppearTimes[s.charAt(right) - 'A']这种写法
-
采用左右指针的方式, 如果需要扩大窗口, 那么right++, 然后增加新添加字符的次数
-
如果是窗口滑动, 那么left ++ , right ++ , 同时需要移除窗口最左边的元素, 移入右边的元素, 完成相应次数的加减. charAppearTimes[s.charAt(left) - 'A'] -= 1;这个就没注意, 老写错