Longest Repeating Character Replacement
Question statment
You are given a string s
and an integer k
. You can choose any character of the string and change it to any other uppercase English character. You can perform this operation at most k
times.
Return the length of the longest substring containing the same letter you can get after performing the above operations.
Example
Input: s = "ABAB", k = 2
Output: 4
Explanation: Replace the two 'A's with two 'B's or vice versa.
Input: s = "AABABBA", k = 1
Output: 4
Explanation: Replace the one 'A' in the middle with 'B' and form "AABBBBA".
The substring "BBBB" has the longest repeating letters, which is 4.
There may exists other ways to achive this answer too.
Solution
For this one, it's important to not overthink it. The question is asking us to replace k
character but actually it's just looking for the longest length that has most k
character difference.
This can simply calculate using this formula:
$$ currentLength - mostFrequentCharacterLength \leq k$$
If this condition is satisfied, we will calculate it to store the maxLength
.
For example, given a string:
s = AABBAABBACAB, k = 2
at 1 certain point
v
AABBAABBACAB
^
Following the formula, we know that this string BBAABB
satisfies the condition:
- $currentLength$: 6
- $mostFrequentCharacterLength$ : 4 (4
B
's)
And 7-4 <= 2
therefore the string satisfies that we can replace k
character to make the string valid.
Using the same concept, we can solve this with Fast and Slow pointers. Creating a window.
- We increment
fast
for every string we go through - We increment
slow
when we have an invalid window. Therefore, we want to decrease the size of our window to reduce $currentLength$ which potentially brings it to be smaller than k- When increment
slow
, we also remove the previous letter from the count, therefore also potentially lessen $mostFrequentCharacterLength$
- When increment
Implementation
class App:
def characterReplacement(self, s: str, k: int) -> int:
if len(s) <= k: return len(s)
frequency = Counter()
slow, fast = 0, 0
maxLength = 0
while (fast < len(s)):
frequency[s[fast]] += 1
currentStringLength = fast - slow + 1
while currentStringLength - self.getMaxFrequency(frequency) > k:
frequency[s[slow]] -= 1
slow += 1
currentStringLength = fast - slow + 1
maxLength = max(maxLength, currentStringLength)
fast += 1
return maxLength
def getMaxFrequency(self, frequency: Dict[str, int]) -> int:
return max(frequency.values())
Time Complexity: $O(26n)$
getMaxFrequency()
is $O(26)$ since there are 26 characters in the alphabets
Space Complexity: $O(26)$- to store the
frequency
array