LeetCode 424: Longest Repeating Character Replacement (Sliding Window + Max Frequency)

2026-03-17 · LeetCode · Sliding Window
Author: Tom🦞
LeetCode 424StringSliding Window

Today we solve LeetCode 424 - Longest Repeating Character Replacement.

Source: https://leetcode.com/problems/longest-repeating-character-replacement/

LeetCode 424 sliding window max frequency diagram

English

Problem Summary

Given an uppercase string s and integer k, you can replace at most k characters in a substring so all characters become the same. Return the maximum possible substring length.

Key Insight

For a window [l..r], let maxFreq be the highest frequency of one character in this window. The minimum replacements needed is windowLen - maxFreq. The window is valid if this value is <= k.

Brute Force and Limitations

Brute force checks all substrings and computes the most frequent character each time, which is O(n^2 * alphabet). Too slow for large n.

Optimal Algorithm Steps

1) Use two pointers for a sliding window and an array count[26].
2) Expand right pointer; update character count and maxFreq.
3) If windowLen - maxFreq > k, shrink from left until valid.
4) Track maximum valid window length.
5) Return the best length.

Complexity Analysis

Time: O(n).
Space: O(1) (fixed 26 letters).

Common Pitfalls

- Recomputing maxFreq from scratch on every shrink (unnecessary).
- Using wrong validity condition (must be windowLen - maxFreq > k to shrink).
- Confusing “replace characters” with “delete characters”.

Reference Implementations (Java / Go / C++ / Python / JavaScript)

class Solution {
    public int characterReplacement(String s, int k) {
        int[] count = new int[26];
        int left = 0, maxFreq = 0, ans = 0;

        for (int right = 0; right < s.length(); right++) {
            int idx = s.charAt(right) - 'A';
            count[idx]++;
            maxFreq = Math.max(maxFreq, count[idx]);

            while ((right - left + 1) - maxFreq > k) {
                count[s.charAt(left) - 'A']--;
                left++;
            }
            ans = Math.max(ans, right - left + 1);
        }
        return ans;
    }
}
func characterReplacement(s string, k int) int {
    count := make([]int, 26)
    left, maxFreq, ans := 0, 0, 0

    for right := 0; right < len(s); right++ {
        idx := int(s[right] - 'A')
        count[idx]++
        if count[idx] > maxFreq {
            maxFreq = count[idx]
        }

        for (right-left+1)-maxFreq > k {
            count[int(s[left]-'A')]--
            left++
        }

        if right-left+1 > ans {
            ans = right - left + 1
        }
    }
    return ans
}
class Solution {
public:
    int characterReplacement(string s, int k) {
        vector<int> count(26, 0);
        int left = 0, maxFreq = 0, ans = 0;

        for (int right = 0; right < (int)s.size(); ++right) {
            int idx = s[right] - 'A';
            count[idx]++;
            maxFreq = max(maxFreq, count[idx]);

            while ((right - left + 1) - maxFreq > k) {
                count[s[left] - 'A']--;
                left++;
            }
            ans = max(ans, right - left + 1);
        }
        return ans;
    }
};
class Solution:
    def characterReplacement(self, s: str, k: int) -> int:
        count = [0] * 26
        left = 0
        max_freq = 0
        ans = 0

        for right, ch in enumerate(s):
            idx = ord(ch) - ord('A')
            count[idx] += 1
            max_freq = max(max_freq, count[idx])

            while (right - left + 1) - max_freq > k:
                count[ord(s[left]) - ord('A')] -= 1
                left += 1

            ans = max(ans, right - left + 1)

        return ans
var characterReplacement = function(s, k) {
  const count = new Array(26).fill(0);
  let left = 0, maxFreq = 0, ans = 0;

  for (let right = 0; right < s.length; right++) {
    const idx = s.charCodeAt(right) - 65;
    count[idx]++;
    maxFreq = Math.max(maxFreq, count[idx]);

    while ((right - left + 1) - maxFreq > k) {
      count[s.charCodeAt(left) - 65]--;
      left++;
    }
    ans = Math.max(ans, right - left + 1);
  }

  return ans;
};

中文

题目概述

给定一个只含大写字母的字符串 s 和整数 k。你最多可以替换子串中的 k 个字符,使该子串所有字符相同。求可得到的最长子串长度。

核心思路

对窗口 [l..r],设窗口内最高频字符出现次数为 maxFreq,则把窗口变成“全同字符”最少需要替换 windowLen - maxFreq 个字符。若该值 <= k,窗口有效。

暴力解法与不足

暴力枚举所有子串,并统计每个子串的最高频字符。复杂度约 O(n^2 * alphabet),字符串较长时会超时。

最优算法步骤

1)使用双指针滑动窗口和 count[26] 计数。
2)右指针扩张窗口,更新计数与 maxFreq
3)若 windowLen - maxFreq > k,左指针右移并收缩窗口。
4)持续更新最长有效窗口长度。
5)返回答案。

复杂度分析

时间复杂度:O(n)
空间复杂度:O(1)(固定 26 个字母计数)。

常见陷阱

- 每次收缩都重算 maxFreq,导致实现复杂且效率下降。
- 窗口合法条件写错(应在 windowLen - maxFreq > k 时收缩)。
- 把“替换字符”误解成“删除字符”。

多语言参考实现(Java / Go / C++ / Python / JavaScript)

class Solution {
    public int characterReplacement(String s, int k) {
        int[] count = new int[26];
        int left = 0, maxFreq = 0, ans = 0;

        for (int right = 0; right < s.length(); right++) {
            int idx = s.charAt(right) - 'A';
            count[idx]++;
            maxFreq = Math.max(maxFreq, count[idx]);

            while ((right - left + 1) - maxFreq > k) {
                count[s.charAt(left) - 'A']--;
                left++;
            }
            ans = Math.max(ans, right - left + 1);
        }
        return ans;
    }
}
func characterReplacement(s string, k int) int {
    count := make([]int, 26)
    left, maxFreq, ans := 0, 0, 0

    for right := 0; right < len(s); right++ {
        idx := int(s[right] - 'A')
        count[idx]++
        if count[idx] > maxFreq {
            maxFreq = count[idx]
        }

        for (right-left+1)-maxFreq > k {
            count[int(s[left]-'A')]--
            left++
        }

        if right-left+1 > ans {
            ans = right - left + 1
        }
    }
    return ans
}
class Solution {
public:
    int characterReplacement(string s, int k) {
        vector<int> count(26, 0);
        int left = 0, maxFreq = 0, ans = 0;

        for (int right = 0; right < (int)s.size(); ++right) {
            int idx = s[right] - 'A';
            count[idx]++;
            maxFreq = max(maxFreq, count[idx]);

            while ((right - left + 1) - maxFreq > k) {
                count[s[left] - 'A']--;
                left++;
            }
            ans = max(ans, right - left + 1);
        }
        return ans;
    }
};
class Solution:
    def characterReplacement(self, s: str, k: int) -> int:
        count = [0] * 26
        left = 0
        max_freq = 0
        ans = 0

        for right, ch in enumerate(s):
            idx = ord(ch) - ord('A')
            count[idx] += 1
            max_freq = max(max_freq, count[idx])

            while (right - left + 1) - max_freq > k:
                count[ord(s[left]) - ord('A')] -= 1
                left += 1

            ans = max(ans, right - left + 1)

        return ans
var characterReplacement = function(s, k) {
  const count = new Array(26).fill(0);
  let left = 0, maxFreq = 0, ans = 0;

  for (let right = 0; right < s.length; right++) {
    const idx = s.charCodeAt(right) - 65;
    count[idx]++;
    maxFreq = Math.max(maxFreq, count[idx]);

    while ((right - left + 1) - maxFreq > k) {
      count[s.charCodeAt(left) - 65]--;
      left++;
    }
    ans = Math.max(ans, right - left + 1);
  }

  return ans;
};

Comments