medium

Longest Repeating Character Replacement

Find the longest substring you can turn into one repeated letter with a limited number of swaps.

1. Define the problem

Longest Repeating Character Replacement

Given a string s and an integer k, return the length of the longest substring you can make all the same letter with at most k replacements . A window is valid when length minus the count of its majority character is at most k; shrink left when that budget is exceeded.

Constraints

  • 1 ≤ s.length ≤ 105
  • s consists of only uppercase English letters
  • 0 ≤ k ≤ s.length

Example

Inputs = "AABABBA", k = 1
Output4

Explanation Replace one B in "AABA" or one A in "ABBA" to get a run of 4.

2. Visualize the solution

Keep replacements within k

Keep replacements within k
Statusvalid

Window "AAB": majority A=2, replacements 1 <= k; best = 3.

What happens in this step

window = [0, 2]  ("AAB")

before: counts = {A:2}, maxCount = 2 (from right = 1)
  add s[2] = 'B' → counts = {A:2, B:1}, maxCount stays 2

window length 3, replacements needed = 3 − 2 = 1 ≤ k(1) — valid; best becomes 3.
Step 1 of 5

Steps to visualize

  1. Grow right and bump the count of the entering character.
  2. Track the majority count in the window (most frequent letter).
  3. Replacements needed equal window length minus majority count.
  4. When that exceeds k, shrink left and drop the leaving character.
  5. Track the longest window that stays within the replacement budget.
3. Walk through the code

Walk through the code

Same walkthrough, now with the code. Press Next to move one step and watch which lines run.

Keep replacements within k
Statusvalid

Window "AAB": majority A=2, replacements 1 <= k; best = 3.

What happens in this step

window = [0, 2]  ("AAB")

before: counts = {A:2}, maxCount = 2 (from right = 1)
  add s[2] = 'B' → counts = {A:2, B:1}, maxCount stays 2

window length 3, replacements needed = 3 − 2 = 1 ≤ k(1) — valid; best becomes 3.
Step 1 of 5
4. Solution

Solution

solution.tsTypeScript
function characterReplacement(s, k) {
  const counts = new Map();
  let left = 0;
  let maxCount = 0;
  let best = 0;

  for (let right = 0; right < s.length; right++) {
    const c = s[right];
    counts.set(c, (counts.get(c) ?? 0) + 1);
    maxCount = Math.max(maxCount, counts.get(c));

    const windowLen = right - left + 1;
    if (windowLen - maxCount > k) {
      const leftChar = s[left];
      counts.set(leftChar, counts.get(leftChar) - 1);
      left++;
    }

    best = Math.max(best, right - left + 1);
  }

  return best;
}
Time
O(n)
Space
O(1)
5. Test cases

Test cases

InputExpectedCovers
s = "AABABBA", k = 14Docstring example
s = "A", k = 01Single character
s = "AAAA", k = 24Entire string already one character
s = "ABCDE", k = 01k = 0 with no repeats
s = "BBBB", k = 04All identical elements
s = "ABCD", k = 34k covers the whole string
s = "ABAB", k = 24Replace both B's with A
s = "AABABBA", k = 02Classic second example with k = 0