LeetCode ยท #424

Longest Repeating Character Replacement Solution

Given a string s and an integer k, find the length of the longest substring you can get by replacing at most k characters.

01
Section One ยท Problem

Problem Statement

๐Ÿท๏ธ

Difficulty

Medium

๐Ÿ”—

LeetCode

Problem #424

๐Ÿ—๏ธ

Pattern

Sliding Window โ€” variable size

You are given a string s consisting of uppercase English letters, and an integer k. You can choose any character and change it to any other uppercase letter. You can perform this operation at most k times. Return the length of the longest substring containing the same letter after performing at most k replacements.

Example 1
Input: s = "ABAB", k = 2 Output: 4 // Replace both 'A's with 'B' (or vice versa) โ†’ "BBBB" or "AAAA"
Example 2
Input: s = "AABABBA", k = 1 Output: 4 // Replace s[3]='B' โ†’ "AAAABBA" โ€” substring "AAAA" has length 4
Constraints
โ€ข 1 โ‰ค s.length โ‰ค 10โต โ€ข s consists of uppercase English letters only โ€ข 0 โ‰ค k โ‰ค s.length
02
Section Two ยท Approach 1

Brute Force โ€” O(26ยทnยฒ)

For each possible substring, count the most frequent character. If length - maxFreq โ‰ค k, the substring is valid (we can replace the minority characters). Check all substrings and track the longest valid one.

Problem: O(nยฒ) substrings, each needing a frequency count. A sliding window maintains frequency counts incrementally, expanding right and shrinking left when the window becomes invalid โ€” bringing it to O(n).
Java โ€” Brute Force
class Solution { public int characterReplacement(String s, int k) { int max = 0; for (int i = 0; i < s.length(); i++) { int[] count = new int[26]; int maxFreq = 0; for (int j = i; j < s.length(); j++) { count[s.charAt(j) - 'A']++; maxFreq = Math.max(maxFreq, count[s.charAt(j) - 'A']); if (j - i + 1 - maxFreq <= k) max = Math.max(max, j - i + 1); } } return max; } }
Python โ€” Brute Force
class Solution: def characterReplacement(self, s: str, k: int) -> int: max_len = 0 for i in range(len(s)): count = {} max_freq = 0 for j in range(i, len(s)): count[s[j]] = count.get(s[j], 0) + 1 max_freq = max(max_freq, count[s[j]]) if (j - i + 1) - max_freq <= k: max_len = max(max_len, j - i + 1) return max_len
MetricValue
TimeO(nยฒ)
SpaceO(1) โ€” 26-slot array
03
Section Three ยท Approach 2

Sliding Window โ€” O(n)

Maintain a window [left, right] with a frequency array. Track maxFreq โ€” the count of the most frequent character in the window. The window is valid when windowSize - maxFreq โ‰ค k (we can replace the non-dominant characters). When invalid, shrink from the left.

๐Ÿ’ก Mental model: You have a paint roller that can cover k wrong-colored tiles. Stretch the roller rightward over the wall. As long as the number of tiles that don't match the most common color is โ‰ค k, the roller works. When too many mismatches appear, slide the left end forward to reduce them.
Algorithm
  • Step 1: left = 0, maxFreq = 0, frequency array count[26].
  • Step 2: For each right: increment count[s[right]], update maxFreq.
  • Step 3: While (right - left + 1) - maxFreq > k: decrement count[s[left]], left++.
  • Step 4: Update result = max(result, right - left + 1).
๐ŸŽฏ Key insight โ€” maxFreq never needs to decrease:
  • We only care about the largest valid window.
  • If maxFreq decreases (because the frequent char left the window), the window can't be larger than the previous best anyway.
  • So we don't need to recompute the true max frequency after shrinking โ€” we only update maxFreq when it increases.
  • This is what makes the algorithm O(n) instead of O(26n).
04
Section Four ยท Trace

Visual Walkthrough

Trace through s = "AABABBA", k = 1:

Sliding Window โ€” expand right, shrink left when replacements > k
STRING A A B A B B A 0 1 2 3 4 5 6 Window valid when: windowSize โˆ’ maxFreq โ‰ค k(=1) r=0: [A] maxF=1, 1-1=0โ‰ค1 โœ“ len=1 r=1: [AA] maxF=2, 2-2=0โ‰ค1 โœ“ len=2 r=2: [AAB] maxF=2, 3-2=1โ‰ค1 โœ“ len=3 r=3: [AABA] maxF=3, 4-3=1โ‰ค1 โœ“ len=4 โ† max! r=4: [AABAB] maxF=3, 5-3=2>1 โœ— โ†’ shrink L remove s[0]='A', L=1 โ†’ [ABAB] 4-2=2>1 โ†’ L=2 โ†’ [BAB] 3-2=1โ‰ค1 โœ“ len=3 r=5: [BABB] maxF=3, 4-3=1โ‰ค1 โœ“ len=4 ties max r=6: [BABBA] 5-3=2>1 โ†’ shrink โ†’ len stays 4 Answer: 4 โœ“
05
Section Five ยท Implementation

Code โ€” Java & Python

Java โ€” Sliding Window
class Solution { public int characterReplacement(String s, int k) { int[] count = new int[26]; int left = 0, maxFreq = 0, result = 0; for (int right = 0; right < s.length(); right++) { count[s.charAt(right) - 'A']++; maxFreq = Math.max(maxFreq, count[s.charAt(right) - 'A']); while (right - left + 1 - maxFreq > k) { count[s.charAt(left) - 'A']--; left++; } result = Math.max(result, right - left + 1); } return result; } }
Python โ€” Sliding Window
class Solution: def characterReplacement(self, s: str, k: int) -> int: count = {} left = max_freq = result = 0 for right in range(len(s)): count[s[right]] = count.get(s[right], 0) + 1 max_freq = max(max_freq, count[s[right]]) while (right - left + 1) - max_freq > k: count[s[left]] -= 1 left += 1 result = max(result, right - left + 1) return result
06
Section Six ยท Analysis

Complexity Analysis

ApproachTimeSpaceTrade-off
Brute ForceO(nยฒ)O(1)Check all substrings
Sliding Window โ† optimal O(n) O(1) 26-slot array; each char enters/leaves window once
07
Section Seven ยท Edge Cases

Edge Cases & Pitfalls

CaseInputWhy It Matters
k โ‰ฅ n"ABC", k=3Can replace everything โ†’ answer is n.
k = 0"AABBA", k=0No replacements โ€” find longest run of same char. "AA" โ†’ 2.
All same"AAAA", k=2Already uniform โ€” answer is n.
Single char"A", k=0Trivial โ€” answer is 1.
Alternating"ABABAB", k=2Can make "AAAAAB" โ†’ 5 or similar. Window expands to 5.
โš  Common Mistake: Recomputing maxFreq by scanning the entire frequency array after each left-shrink. This is unnecessary โ€” maxFreq only needs to increase for larger windows to beat the current best. Leaving it at its historical max is both correct and faster.

โ† Back to Sliding Window problems