题目

给你一个字符串 s 和一个整数 k 。你可以选择字符串中的任一字符,并将其更改为任何其他大写英文字符。该操作最多可执行 k 次。

在执行上述操作后,返回包含相同字母的最长子字符串的长度。

示例 1:

输入:s = “ABAB”, k = 2
输出:4
解释:用两个’A’替换为两个’B’,反之亦然。

示例 2:

输入:s = “AABABBA”, k = 1
输出:4
解释:
将中间的一个’A’替换为’B’,字符串变为 “AABBBBA”。
子串 “BBBB” 有最长重复字母, 答案为 4。

提示:

1 <= s.length <= 10^5
s 仅由大写英文字母组成
0 <= k <= s.length

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/longest-repeating-character-replacement
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

滑窗思路,统计滑窗内最高频次的字符,最多允许有k个不同的字符,即需要满足len(滑窗)-maxCnt<=k,其中maxCnt为滑窗内频次最高的字符次数。

因为字符串全部是大写字母,因此,使用一个数组统计字符频次,并实时更新maxCnt。剩下的就是常规的滑窗写法。

需要注意的是,当滑窗左边界收缩时,mCnt的定义不用维护,原因「官解」说的很清楚了,确实有点不太好理解,这里就不说明了。

代码

  1. class Solution {
  2. public int characterReplacement(String s, int k) {
  3. int n = s.length();
  4. int[] cnt = new int[26];
  5. int left = 0;
  6. int right = 0;
  7. int ans = 0;
  8. int mCnt = 0;
  9. while (right < n) {
  10. cnt[s.charAt(right) - 'A']++;
  11. mCnt = Math.max(mCnt, cnt[s.charAt(right) - 'A']);
  12. while (right - left + 1 - mCnt > k) {
  13. cnt[s.charAt(left) - 'A']--;
  14. left++;
  15. }
  16. ans = Math.max(ans, right - left + 1);
  17. right++;
  18. }
  19. return ans;
  20. }
  21. }