You are given a string s
and an integer repeatLimit
. Construct a new string repeatLimitedString
using the characters of s
such that no letter appears more than repeatLimit
times in a row. You do not have to use all characters from s
.
Return the lexicographically largest repeatLimitedString
possible.
A string a
is lexicographically larger than a string b
if in the first position where a
and b
differ, string a
has a letter that appears later in the alphabet than the corresponding letter in b
. If the first min(a.length, b.length)
characters do not differ, then the longer string is the lexicographically larger one.
Example 1:
Input: s = "cczazcc", repeatLimit = 3 Output: "zzcccac" Explanation: We use all of the characters from s to construct the repeatLimitedString "zzcccac". The letter 'a' appears at most 1 time in a row. The letter 'c' appears at most 3 times in a row. The letter 'z' appears at most 2 times in a row. Hence, no letter appears more than repeatLimit times in a row and the string is a valid repeatLimitedString. The string is the lexicographically largest repeatLimitedString possible so we return "zzcccac". Note that the string "zzcccca" is lexicographically larger but the letter 'c' appears more than 3 times in a row, so it is not a valid repeatLimitedString.
Example 2:
Input: s = "aababab", repeatLimit = 2 Output: "bbabaa" Explanation: We use only some of the characters from s to construct the repeatLimitedString "bbabaa". The letter 'a' appears at most 2 times in a row. The letter 'b' appears at most 2 times in a row. Hence, no letter appears more than repeatLimit times in a row and the string is a valid repeatLimitedString. The string is the lexicographically largest repeatLimitedString possible so we return "bbabaa". Note that the string "bbabaaa" is lexicographically larger but the letter 'a' appears more than 2 times in a row, so it is not a valid repeatLimitedString.
Constraints:
1 <= repeatLimit <= s.length <= 105
s
consists of lowercase English letters.When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force strategy for constructing a string with repeat limits means trying every possible combination of characters until we find one that works. We will build the string character by character, ensuring we never exceed the repeat limit for any character. This involves an exhaustive search to explore all viable arrangements.
Here's how the algorithm would work step-by-step:
def construct_string_with_repeat_limit_brute_force(characters, repeat_limit):
characters.sort(reverse=True)
max_length = sum(frequency for char, frequency in characters)
def backtrack(current_string, remaining_characters):
if len(current_string) == max_length:
return current_string
best_string = ""
for index in range(len(remaining_characters)):
character, frequency = remaining_characters[index]
# Check if we can add the current character without exceeding the repeat limit.
if len(current_string) > 0 and current_string[-1] == character:
last_char_count = 0
for i in range(len(current_string) - 1, -1, -1):
if current_string[i] == character:
last_char_count += 1
else:
break
if last_char_count == repeat_limit:
continue
# If the character is available, try adding it.
if frequency > 0:
new_string = current_string + character
new_remaining_characters = remaining_characters[:index] + \
[(character, frequency - 1)] + \
remaining_characters[index + 1:]
new_remaining_characters.sort(reverse=True)
# Recursively call backtrack to explore further possibilities.
result = backtrack(new_string, new_remaining_characters)
if len(result) == max_length:
return result
if len(result) > len(best_string):
best_string = result
return best_string
# Initiate backtracking from an empty string.
result = backtrack("", characters)
return result
To build the string efficiently, we'll focus on using the most frequent characters first, limiting repetition. We'll prioritize using the most available letters to construct the string in a greedy manner while respecting the repetition limit.
Here's how the algorithm would work step-by-step:
def construct_string_with_repeat_limit(input_string, repeat_limit):
letter_counts = {}
for char in input_string:
letter_counts[char] = letter_counts.get(char, 0) + 1
sorted_letter_counts = sorted(letter_counts.items(), key=lambda item: item[1], reverse=True)
result = ""
while sorted_letter_counts:
most_frequent_letter, most_frequent_count = sorted_letter_counts[0]
# Add the most frequent letter up to the repeat limit or available count.
add_count = min(most_frequent_count, repeat_limit)
result += most_frequent_letter * add_count
sorted_letter_counts[0] = (most_frequent_letter, most_frequent_count - add_count)
if sorted_letter_counts[0][1] == 0:
sorted_letter_counts.pop(0)
continue
# If more of the most frequent letter remains, find a different letter to insert.
if sorted_letter_counts:
second_most_frequent_letter, second_most_frequent_count = sorted_letter_counts[0]
result += second_most_frequent_letter
sorted_letter_counts[0] = (second_most_frequent_letter, second_most_frequent_count - 1)
# Remove if count becomes zero.
if sorted_letter_counts[0][1] == 0:
sorted_letter_counts.pop(0)
# Re-sort the list to maintain the order of frequency
sorted_letter_counts = sorted(sorted_letter_counts, key=lambda item: item[1], reverse=True)
else:
# No other letters to break the streak, construction is impossible.
return ""
return result
Case | How to Handle |
---|---|
Empty input string s | Return an empty string since there are no characters to construct from. |
repeatLimit is 0 | Return an empty string, as no character can be repeated consecutively. |
repeatLimit is 1 | Return the string sorted in reverse lexicographical order as no character can appear more than once consecutively. |
Input string contains only one unique character and its count is less than or equal to repeatLimit | Return the original string since it already satisfies the condition. |
Input string contains only one unique character and its count is greater than repeatLimit | Return the character repeated repeatLimit times, as that's the maximum possible string. |
All characters in the input string are the same. | Return the character repeated repeatLimit times, as any longer string will violate the repeat limit. |
The lexicographically largest character has a count exceeding repeatLimit, and there are no other characters in the string. | Return the lexicographically largest character repeated repeatLimit times. |
Input string with a skewed distribution where one or two characters are much more frequent than others. | Prioritize the largest character while respecting the repeat limit, switching to smaller characters to satisfy the condition and prevent over-repetition. |