Longest Repeated Character Replacement

Ethan Davis
Data Structures and Algorithms DSA
2 min readMay 24, 2024
Data Structures and Algorithms

Statement

Given a string s and integer k, find the length of the longest substring of s, such that all characters of that substring are identical after replacing at most k characters with any other character.

Constraints

  • -1 ≤ s.length() ≤ 10³
  • 0 ≤ ks.length()
  • s consists of only lowercase English characters

Solution

"""
production algorithm
"""

from collections import defaultdict


class Solution:
def longest_repeated_character_replacement(self, string, capacity):
"""
time complexity O(n)
space complexity O(1)
"""
length, low, high = len(string), 0, 0
max_frequency, frequencies = -1, defaultdict(int)

for high in range(length):
frequencies[string[high]] = frequencies[string[high]] + 1
max_frequency = max(max_frequency, frequencies[string[high]])
if capacity < high - low + 1 - max_frequency:
frequencies[string[low]] = frequencies[string[low]] - 1
low = low + 1

return high - low + 1
"""
unit tests
"""

from unittest import TestCase
from algorithms.sliding_window.longest_repeated_character_replacement.solution import Solution


class SolutionTestCase(TestCase):
def test_longest_repeated_contiguous_at_start(self):
# Given
string = "aaaaaaaaaaxerkjysuhf"
capacity = 2
solution = Solution()

# When
actual = solution.longest_repeated_character_replacement(
string, capacity)

# Then
expected = 12
self.assertEqual(actual, expected)

def test_longest_repeated_contiguous_at_middle(self):
# Given
string = "wzomqaaaaaaaaaaysuhf"
capacity = 2
solution = Solution()

# When
actual = solution.longest_repeated_character_replacement(
string, capacity)

# Then
expected = 12
self.assertEqual(actual, expected)

def test_longest_repeated_contiguous_at_end(self):
# Given
string = "wzomqvtnlbaaaaaaaaaa"
capacity = 2
solution = Solution()

# When
actual = solution.longest_repeated_character_replacement(
string, capacity)

# Then
expected = 12
self.assertEqual(actual, expected)

def test_longest_repeated_noncontiguous_at_start(self):
# Given
string = "aaaaavaaaaaerkjysuhf"
capacity = 2
solution = Solution()

# When
actual = solution.longest_repeated_character_replacement(
string, capacity)

# Then
expected = 12
self.assertEqual(actual, expected)

def test_longest_repeated_noncontiguous_at_middle(self):
# Given
string = "wzoaaaaalbaaaaaysuhf"
capacity = 2
solution = Solution()

# When
actual = solution.longest_repeated_character_replacement(
string, capacity)

# Then
expected = 12
self.assertEqual(actual, expected)

def test_longest_repeated_noncontiguous_at_end(self):
# Given
string = "wzomqvtnlaaaaajaaaaa"
capacity = 2
solution = Solution()

# When
actual = solution.longest_repeated_character_replacement(
string, capacity)

# Then
expected = 12
self.assertEqual(actual, expected)

Strategy

Sliding Window.

Explanation

At each step of the high index, add the character of the high index to the window and so increment its frequency in the window. If the window has more characters than can be replaced such that all characters in the window are identical, then remove the character of the low index from the window and so decrement its frequency in the window. The algorithm slides a window over all characters of the string, the window widens to the maximum length such that all characters in the window can be identical after replacement, and it never shrinks.

Time Complexity

The time complexity of the algorithm is O(n).

Space Complexity

The auxiliary space complexity of the algorithm is O(1) since at most 26 characters are kept in the frequencies store.

Links

--

--