>

Longest Repeating Character Replacement

"""
424. Longest Repeating Character Replacement

https://leetcode.com/problems/longest-repeating-character-replacement

NOTES
  * Use a sliding window.

This is a hard one. The key insight is that a substring is valid (i.e., the
substring contains only one unique character after performing k replacements)
when:

  window size - frequency of most common character ≤ k

Initially, I inverted the logic, searching instead for the longest substring
with > k replacements. The correct solution is pretty straightforward *if* you
are working from the above premise. Additionally, I've added the canonical
sliding window implementation. Its form should look familiar...
"""

from collections import Counter


class Solution:
    def characterReplacement(self, s: str, k: int) -> int:
        left, right, maximum_size = 0, 0, 0

        # Maintain a mapping of character -> frequency. Likewise, keep track
        # of the most common character (i.e, the maximum frequency character).
        counter: Counter[str] = Counter()
        maximum_frequency = 0

        while right < len(s):
            counter[s[right]] += 1

            # Update the maximum frequency.
            maximum_frequency = max(maximum_frequency, counter[s[right]])

            # Check to see if the current substring is valid. Remember, a
            # substring is valid if:
            #
            #   window size - frequency of most common character ≤ k
            #
            # If the window is invalid, increment left, which invariably will
            # result in a valid substring.
            if (right - left + 1) - maximum_frequency > k:
                counter[s[left]] -= 1
                left += 1

            maximum_size = max(maximum_size, right - left + 1)
            right += 1

        return maximum_size


class CanonicalSolution:
    def characterReplacement(self, s: str, k: int) -> int:
        left, right, maximum_size = 0, 0, 0

        # Maintain a mapping of character -> frequency.
        counter: Counter[str] = Counter()
        maximum_frequency = 0

        while right < len(s):
            counter[s[right]] += 1
            maximum_frequency = max(maximum_frequency, counter[s[right]])
            # Invariant: left <= right and substring is invalid.
            while left <= right and (right - left + 1) - maximum_frequency > k:
                counter[s[left]] -= 1
                left += 1
            maximum_size = max(maximum_size, right - left + 1)
            right += 1

        return maximum_size
Source | LeetCode

grind.rip

From Grind Hell, with Love