Problem Statement in English
You’re given a string s, and an integer k.
Your task is to determine the longest substring in s built of the same character. You’re allowed to replace any k characters from the substring with any letter you like, in order to meet the requirement.
Approach
Brute forcing this is definitely an option, but we can do better. Hence we won’t go into the nested loop approach.
We’ll cover the linear time approach that uses the Sliding Window technique with a dynamic window size. The mechanics of this approach have been discussed in this problem.
However, this problem needs us to build upon that base model.
In particular, we need a mechanism to keep track of whether we can ensure that all characters in the window are the same character. This sounds way harder than it actually is.
First off, we need to maintain the frequency of each character occuring in the current window. A frequency map. I’ve called this the registry.
Secondly, we need to check if we can convert all character in the window to be the same character. The way we do this, is by using that frequency map, and checking if the the difference between all frequencies and the frequency of the highest occuring value is lesser <= k.
Why?
This is because the value with the highest frequency is what we’d replace all other characters with. So we need to check if we’ve our replacement allowance provides for us to replace every other character with the highest occuring one.
Solution in Python
class Solution:
def characterReplacement(self, s: str, k: int) -> int:
# tracks longest substring
# that satisfies the requirements
ans = 0
# tracks frequency of characters
registry = {}
# left pointer
l = 0
# move right pointer forward
for r in range(len(s)):
# update frequency map
# based on new character
# pointed to by right pointer
if s[r] in registry:
registry[s[r]] += 1
else:
registry[s[r]] = 1
# while we can't replace all characters
# in the window to be the same character
while (r - l + 1) - max(registry.values()) > k:
# since we're going to move the left pointer forward,
# the frequency contribution by the character
# pointed to by left must be decremented
registry[s[l]] -= 1
# compaction, this is optional
# helps if there's a lot of distinct characters in the string
#
# actually no...just realized there can only be 26 ;(
# sighh
if registry[s[l]] == 0:
del registry[s[l]]
# move left pointer forward
l += 1
# update the longest length substring,
# if need be
ans = max(ans, r - l + 1)
# return answer
return ans
Complexity
Time:
Since we process elements at most.Space:
Since we store elements at most in theMap.
Mistakes I Made
I used the following condition in the while loop:
while sum(registry.values()) - max(registry.values()) > k:
instead of
while (r - l + 1) - max(registry.values()) > k:
🤦♂️.
And we are done.