There is a strange printer with the following two special properties:
- The printer can only print a sequence of the same character each time.
- At each turn, the printer can print new characters starting from and ending at any place and will cover the original existing characters.
Given a string s
, return the minimum number of turns the printer needed to print it.
Example 1:
Input: s = "aaabbb" Output: 2 Explanation: Print "aaa" first and then print "bbb".
Example 2:
Input: s = "aba" Output: 2 Explanation: Print "aaa" first and then print "b" from the second place of the string, which will cover the existing character 'a'.
Constraints:
1 <= s.length <= 100
s
consists of lowercase English letters.
Approach 01:
-
C++
-
Python
class Solution { public: int strangePrinter(string s) { const int length = s.length(); vector<vector<int>> memo(length, vector<int>(length)); // Start the recursive function to find the minimum number of turns // needed to print the entire string. return findMinTurns(s, 0, length - 1, memo); } private: // This function returns the minimum number of turns required to print the substring s[start..end]. int findMinTurns(const string& s, int start, int end, vector<vector<int>>& memo) { // Base case: if the start index exceeds the end index, no turns are needed. if (start > end) return 0; // If the result for this substring has already been computed, return the cached result. if (memo[start][end] > 0){ return memo[start][end]; } // Initialize the minimum turns by assuming we print the character at 'start' separately. memo[start][end] = findMinTurns(s, start + 1, end, memo) + 1; // Try to find any matching characters within the range to optimize the number of turns. for (int mid = start + 1; mid <= end; ++mid) { // If s[mid] matches s[start], consider this as a candidate for reducing the number of turns. if (s[mid] == s[start]) { memo[start][end] = min(memo[start][end], findMinTurns(s, start, mid - 1, memo) + findMinTurns(s, mid + 1, end, memo)); } } // Return the minimum number of turns required to print the substring s[start..end]. return memo[start][end]; } };
class Solution: def strangePrinter(self, s: str) -> int: length = len(s) memo = [[0] * length for _ in range(length)] # Start the recursive function to find the minimum number of turns # needed to print the entire string. return self.findMinTurns(s, 0, length - 1, memo) def findMinTurns(self, s: str, start: int, end: int, memo: list[list[int]]) -> int: # Base case: if the start index exceeds the end index, no turns are needed. if start > end: return 0 # If the result for this substring has already been computed, return the cached result. if memo[start][end] > 0: return memo[start][end] # Initialize the minimum turns by assuming we print the character at 'start' separately. memo[start][end] = self.findMinTurns(s, start + 1, end, memo) + 1 # Try to find any matching characters within the range to optimize the number of turns. for mid in range(start + 1, end + 1): # If s[mid] matches s[start], consider this as a candidate for reducing the number of turns. if s[mid] == s[start]: memo[start][end] = min(memo[start][end], self.findMinTurns(s, start, mid - 1, memo) + self.findMinTurns(s, mid + 1, end, memo)) # Return the minimum number of turns required to print the substring s[start..end]. return memo[start][end]
Time Complexity
- Recursive Function Calls:
The function
findMinTurns
is recursively called for each possible substring ofs
. The number of possible substrings of length \( n \) is \( O(n^2) \). For each substring, the function performs a loop to check potential optimizations, leading to a time complexity of \( O(n) \) for each call. Therefore, the overall time complexity for all recursive calls is \( O(n^3) \). - Memoization:
Since the results of subproblems are stored in the
memo
table, each subproblem is solved only once, further contributing to the \( O(n^3) \) time complexity. - Overall Time Complexity:
The overall time complexity of the algorithm is \( O(n^3) \), where \( n \) is the length of the string
s
.
Space Complexity
- Auxiliary Variables:
The function uses a 2D memoization table
memo
of size \( n \times n \) to store the results of subproblems, where \( n \) is the length of the strings
. The space required for this table is \( O(n^2) \). - Overall Space Complexity:
The overall space complexity of the algorithm is \( O(n^2) \) because of the memoization table.