Skip to content

Sliding Window — Longest Repeating Character Replacement ​

↗ LeetCode: Longest Repeating Character Replacement · Medium · pattern chapter →

Asked atMetaGoogleMicrosoftAmazon

Given s (uppercase A–Z) and integer k, return the length of the longest substring you can make of a single repeated character by replacing at most k other characters.

Example 1 — s = "ABAB", k = 2 → 4 (replace both As or both Bs) Example 2 — s = "AABABBA", k = 1 → 4 (window AABA → replace one A with B, or the reverse) Example 3 — s = "AAAA", k = 0 → 4 (already all same)

Constraints — 1 ≤ n ≤ 10⁵, 0 ≤ k ≤ n. Brute is O(n²·26) ≈ 2.6·10¹¹ ops at n=10⁵ (TLE). Sliding window (max-freq + k) is O(n·26) ≈ 2.6·10⁶ ops.

Progressive Hints
Try to solve it yourself first. Reveal hints only when stuck — each hint is progressively more specific.
---
⏱️Interview timer00:00
Practice under interview pressure. Start when you begin reading; stop when you finish. Save best only when you had a full working solution.
Target for interview: Medium = 20-25 min · Hard = 30-40 min · Best time persists on this device only.

Approach 1 — Try every substring ​

Intuition. For each s[i..j], count the most frequent letter maxFreq; the window is valid iff (j - i + 1) - maxFreq ≤ k. Track the longest.

java
int characterReplacementBrute(String s, int k) {
    int n = s.length(), best = 0;
    for (int i = 0; i < n; i++)
        for (int j = i; j < n; j++) {
            int[] cnt = new int[26], maxFreq = {0};
            for (int p = i; p <= j; p++) {
                cnt[s.charAt(p) - 'A']++;
                maxFreq[0] = Math.max(maxFreq[0], cnt[s.charAt(p) - 'A']);
            }
            if (j - i + 1 - maxFreq[0] <= k) best = Math.max(best, j - i + 1);
        }
    return best;
}
Execution Trace
Brute — s='AABABBA', k=1 checking windows
ijA0A1B2A3B4B5A6window = AABmaxFreq = 2needFlips = 1best = 3
Step 1 / 41 flip fits budget

Complexity — Time O(n³); Space O(1).


Approach 2 — Sliding window with "lazy" maxFreq ​

Insight from brute. The window validity check windowLen - maxFreq ≤ k is monotone in one direction: growing right can only require larger maxFreq (or the same) to keep the window feasible. Grow right; if the window becomes invalid, shrink left by exactly one.

Trap — we don't need to recompute maxFreq when shrinking. Any window with size ≤ current best can't improve the answer regardless of stale maxFreq. So we lazily keep the max ever seen.

java
int characterReplacement(String s, int k) {
    int[] cnt = new int[26];
    int left = 0, maxCount = 0, best = 0;
    for (int right = 0; right < s.length(); right++) {
        cnt[s.charAt(right) - 'A']++;
        maxCount = Math.max(maxCount, cnt[s.charAt(right) - 'A']);
        if (right - left + 1 - maxCount > k)
            cnt[s.charAt(left++) - 'A']--;
        best = Math.max(best, right - left + 1);
    }
    return best;
}
Execution Trace
Sliding — s='AABABBA', k=1
leftrightA0A1B2A3B4B5A6cnt = {A:1}maxCount = 1best = 1
Step 1 / 4start

Complexity — Time O(n); Space O(1) (26 buckets).

Why "lazy max" is safe. The answer we output is never smaller than best. If maxCount is stale (real max is lower), the window only grows if a new character bumps maxCount higher — which is real, not stale. Correctness preserved.


Try it yourself ​

Complexity summary ​

ApproachTimeSpaceInterview grade
Try every substringO(n³)O(1)baseline; TLE at n=10⁵
Sliding window + lazy maxFreqO(n)O(1)expected optimum

When to use which ​

  • First pass — state brute, then jump to sliding window.
  • "At most k operations" signal → try replacing maxFreq with the constrained quantity in the validity formula.
  • "What if alphabet is Unicode?" → replace int[26] with HashMap<Character,Integer>; recomputing max on every shrink is O(σ) — slower but still correct.
  • Follow-up: return the actual substring → track (bestL, bestLen) and slice.
✨AI Study CompanionBeta
Was this page helpful?

Released under MIT license.

💡 Quick shortcuts
H HintsR Run JavaA AI Help