Problem
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.
Examples
Example 1:
|
|
Example 2:
|
|
Solution
Video explanation
Here is the video explaining below methods in detail. Please check it out:
Method 1 - Sliding window with max frequency recalculation
Intuition
This problem is a variant of the problem Longest Substring Without Repeating Characters. We will use a similar sliding-window technique to solve this problem.
The sliding window approach is the optimal solution because we need to track the longest substring where we can replace characters to form contiguous identical characters. By dynamically adjusting the window size and keeping track of the character frequency, we can efficiently calculate the required result.
The max frequency
of characters in the current window is recalculated every time the window size changes by iterating through the frequency counts. While this guarantees correctness, recalculating the max frequency
on every iteration can be computationally a little expensive, but still constant ⇨ O(26) = O(1)
.
Approach
Here is the approach:
- Track Character Frequencies:
- Use a fixed-size frequency array (
counts[26]
) since there are only 26 uppercase English letters.
- Use a fixed-size frequency array (
- Expand Window:
- For each new character added (
s[r]
), update its frequency in thecounts
array.
- For each new character added (
- Check Validity:
- Recalculate the maximum frequency from the counts (
max(counts)
). - If the number of changes (
window size - max frequency
) exceedsk
, shrink the window by moving thel
pointer and adjusting the frequency map.
- Recalculate the maximum frequency from the counts (
- Update Result:
- Continuously update the answer (
ans
) using the valid window size.
- Continuously update the answer (
Code
|
|
|
|
Complexity
- ⏰ Time complexity:
O(26 * n)
=O(n)
for iterating through the string +O(26)
for recalculating the max frequency at each step. Though linear in nature, recalculation adds overhead, making this approach slightly less efficient for long strings. - 🧺 Space complexity:
O(1)
for the frequency array (fixed sizecounts[26]
).
Method 2 - Sliding Window without max frequency recalculation
Intuition
Instead of recalculating the max frequency
from the frequency map on every iteration, maintain a running value (maxCharCount
) that tracks the highest frequency character seen within the current sliding window. This approach avoids frequent scanning of the frequency map, making it more efficient when dealing with large strings.
Approach
- Track Character Frequencies:
- Use a frequency
HashMap
to dynamically count characters in the current window. - Maintain a variable
maxCharCount
to store the highest frequency of any single character in the window.
- Use a frequency
- Expand Window:
- For each new character added (
s[r]
), update its frequency in the map and updatemaxCharCount
if the frequency of the current character becomes higher.
- For each new character added (
- Check Validity:
- Calculate the number of changes (
window size - maxCharCount
). - If this exceeds
k
, shrink the window by decrementing the frequency ofs[l]
and adjusting thel
pointer.
- Calculate the number of changes (
- Update Result:
- Continuously update the answer (
ans
) using the valid window size.
- Continuously update the answer (
Code
|
|
|
|
Complexity
- ⏰ Time complexity:
O(n)
, wheren
is the length of the strings
.O(n)
. Each character is processed a fixed number of times (once when expanding and once when contracting the window). - 🧺 Space complexity:
O(1)
as we only store character frequencies for uppercase English letters (26).