A string is beautiful if:
k
letters of the English lowercase alphabet.2
or more which is a palindrome.You are given a beautiful string s
of length n
and a positive integer k
.
Return the lexicographically smallest string of length n
, which is larger than s
and is beautiful. If there is no such string, return an empty string.
A string a
is lexicographically larger than a string b
(of the same length) if in the first position where a
and b
differ, a
has a character strictly larger than the corresponding character in b
.
"abcd"
is lexicographically larger than "abcc"
because the first position they differ is at the fourth character, and d
is greater than c
.Example 1:
Input: s = "abcz", k = 26
Output: "abda"
Explanation: The string "abda" is beautiful and lexicographically larger than the string "abcz".
It can be proven that there is no string that is lexicographically larger than the string "abcz", beautiful, and lexicographically smaller than the string "abda".
Example 2:
Input: s = "dc", k = 4
Output: ""
Explanation: It can be proven that there is no string that is lexicographically larger than the string "dc" and is beautiful.
Constraints:
1 <= n == s.length <= 10^5
4 <= k <= 26
s
is a beautiful string.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 method tries every possible string that could be the answer. It checks each one to see if it meets the 'beautiful' requirement and picks the smallest one when sorted alphabetically.
Here's how the algorithm would work step-by-step:
def find_lexicographically_smallest_beautiful_string_brute_force(string_value, forbidden_length):
string_length = len(string_value)
smallest_beautiful_string = None
def is_beautiful(test_string):
for index in range(len(test_string) - 1):
if test_string[index] == test_string[index + 1]:
return False
for index in range(len(test_string) - 2):
if ord(test_string[index]) + 1 == ord(test_string[index + 1]) and \
ord(test_string[index + 1]) + 1 == ord(test_string[index + 2]):
return False
return True
def generate_all_strings(current_string, current_length):
nonlocal smallest_beautiful_string
if current_length == string_length:
if is_beautiful(current_string):
# Check if the string is lexicographically smaller.
if smallest_beautiful_string is None or current_string < smallest_beautiful_string:
smallest_beautiful_string = current_string
return
for character_code in range(ord('a'), ord('a') + forbidden_length):
generate_all_strings(current_string + chr(character_code), current_length + 1)
# Initiate string generation
generate_all_strings("", 0)
# Return smallest beautiful string found
return smallest_beautiful_string
The goal is to find the smallest 'beautiful' string possible, based on the alphabet size and forbidden substrings. We'll start from the end and work backwards, making sure to only explore options that are lexicographically smaller and that don't create any bad substrings.
Here's how the algorithm would work step-by-step:
def find_smallest_beautiful_string(string_length, alphabet_size, forbidden_substring):
result = ['a'] * string_length
def is_beautiful(current_string):
for i in range(len(current_string) - 1):
if current_string[i:i+2] == forbidden_substring:
return False
return True
def find_lexicographically_smallest(index):
if index == -1:
return ''.join(result)
for char_code in range(ord('a'), ord('a') + alphabet_size):
potential_char = chr(char_code)
result[index] = potential_char
# Before proceeding, verify no forbidden substring exists.
if index > 0 and result[index-1] + potential_char == forbidden_substring:
continue
# Ensure the new char is smaller than any later characters.
is_smaller_than_later = True
for future_index in range(index + 1, string_length):
if potential_char > result[future_index]:
is_smaller_than_later = False
break
if is_smaller_than_later:
solution = find_lexicographically_smallest(index - 1)
if solution:
return solution
# If no solution is found, backtrack.
result[index] = 'a'
return None
solution = find_lexicographically_smallest(string_length - 1)
if solution and is_beautiful(solution):
return solution
else:
return ""
Case | How to Handle |
---|---|
Empty string input | Return an empty string or an appropriate error, as an empty string cannot be modified to be 'beautiful'. |
k is zero | If k is zero, the string is already beautiful if all adjacent characters are distinct; no changes are needed or possible, so return the original string or handle as an error. |
String length is one | If the string length is 1, it can always be made beautiful as no adjacent characters exist; change the single character to the smallest possible character not equal to its neighbors (which is none), if k > 0. |
String consisting of identical characters with k=1 and length > 1 | The algorithm must correctly alternate characters to make it beautiful, for example 'aaaa' becomes 'ababa'. |
Input string already lexicographically smallest beautiful string | If the input is already the smallest beautiful string (e.g., 'abcabc...' with k=3), the algorithm should return the original string. |
The string cannot be modified to become beautiful given the constraints. | Return an empty string or an appropriate error if generating a beautiful string is impossible (e.g., k = 1 and string consists of repeating one character, or k is smaller than the number of distinct characters). |
Large input string causing potential time limit exceed issues. | Ensure the solution is optimized for time complexity (e.g., avoid unnecessary string manipulations), and consider early termination conditions where applicable. |
Input string contains characters outside the 'a' + k range | Ensure that the input characters are within the allowed range before modification, or throw an IllegalArgumentException otherwise. |