Example 1
ready- Input
s = "ABAB" k = 2- Expected
4- Why
- replace both copies of either letter to make a run of 4
A few well-placed edits can turn a noisy stretch of letters into one clean run.
You're given an uppercase string s and a budget k. You may replace at most k
characters, changing each chosen character to any uppercase English letter. Return the
length of the longest substring — a contiguous stretch — that can become one repeated
letter after those replacements.
A few ground rules:
k replacements, including none.1 <= s.length <= 100_0000 <= k <= s.lengths contains only uppercase English letters A through Z.Hints
In a chosen window, keep its most common letter and replace everything else. If
the window length is w and that letter appears max_count times, the price is
w - max_count replacements.
Move a right edge across the string while counting letters. When the window's
price exceeds k, move the left edge inward until growth is safe again.
The largest letter count you've seen in the active scan never needs to decrease. A stale larger count may delay shrinking, but it can't invent a better answer than the valid window that established that count.
How would your solution change if the input alphabet weren't fixed to 26 letters?
Visible cases
s = "ABAB"
k = 24s = "AABABBA"
k = 14s = "ABCDE"
k = 12Interview signal
For each left edge, extend a right edge and count the 26 letters. A window of length
window_length needs
window_length - max_frequency replacements: keep its most frequent letter and change
the rest.
def character_replacement(s: str, k: int) -> int:
best = 0
for left in range(len(s)):
counts = [0] * 26
for right in range(left, len(s)):
index = ord(s[right]) - ord("A")
counts[index] += 1
max_frequency = max(counts)
window_length = right - left + 1
if window_length - max_frequency <= k:
best = max(best, window_length)
return bestScanning all 26 buckets for every candidate makes the cost explicit. Time O(n² · 26), Space O(26).
The brute force rebuilds nearly the same windows. Keep one sliding window — a contiguous range whose edges move during the scan — and store its 26 letter counts.
As right grows, update max_count, the largest single-letter count reached while the
window grows. If window_length - max_count > k, move left and remove that letter
from the counts.
def character_replacement(s: str, k: int) -> int:
counts = [0] * 26
left = 0
max_count = 0
best = 0
for right, char in enumerate(s):
index = ord(char) - ord("A")
counts[index] += 1
max_count = max(max_count, counts[index])
while right - left + 1 - max_count > k:
left_index = ord(s[left]) - ord("A")
counts[left_index] -= 1
left += 1
best = max(best, right - left + 1)
return bestmax_count may become stale after left moves, and that's deliberate. It records the
majority count that already supported a valid window of this size. A stale value can
keep the current window wide, but the answer grows only when a new character supports a
genuinely larger size.
Each edge moves only forward. Time O(n), Space O(26).
Ready to run.
3 cases are queued.
Visible testcase
Case 1
Expected
4