Two approaches to LeetCode Longest Repeating Character Replacement โ brute force O(nยฒ) and optimal sliding window O(n). Java and Python solutions with visual walkthrough.
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.
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 = 2Output:4// Replace both 'A's with 'B' (or vice versa) โ "BBBB" or "AAAA"
Example 2
Input: s = "AABABBA", k = 1Output: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
classSolution {
publicintcharacterReplacement(String s, int k) {
int max = 0;
for (int i = 0; i < s.length(); i++) {
int[] count = newint[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
classSolution:
defcharacterReplacement(self, s: str, k: int) -> int:
max_len = 0for i in range(len(s)):
count = {}
max_freq = 0for 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
Metric
Value
Time
O(nยฒ)
Space
O(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
05
Section Five ยท Implementation
Code โ Java & Python
Java โ Sliding Window
classSolution {
publicintcharacterReplacement(String s, int k) {
int[] count = newint[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
classSolution:
defcharacterReplacement(self, s: str, k: int) -> int:
count = {}
left = max_freq = result = 0for 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
Approach
Time
Space
Trade-off
Brute Force
O(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
Case
Input
Why It Matters
k โฅ n
"ABC", k=3
Can replace everything โ answer is n.
k = 0
"AABBA", k=0
No replacements โ find longest run of same char. "AA" โ 2.
All same
"AAAA", k=2
Already uniform โ answer is n.
Single char
"A", k=0
Trivial โ answer is 1.
Alternating
"ABABAB", k=2
Can 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.