Lexicographically Smallest Beautiful String - Solution & Explanation
Problem Statement
A string is beautiful if:
- It consists of the first
kletters of the English lowercase alphabet. - It does not contain any substring of length
2or 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.
- For example,
"abcd"is lexicographically larger than"abcc"because the first position they differ is at the fourth character, anddis greater thanc.
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 <= 1054 <= k <= 26sis a beautiful string.
Approach Overview
Problem Overview: You are given a string s and an integer k representing the first k lowercase letters ('a' to 'a' + k - 1). A string is beautiful if no character equals the previous one or the one two positions before it. The task is to find the lexicographically smallest beautiful string strictly greater than s.
Approach 1: Backtrack and Increment (O(n * k) time, O(1) space)
This method treats the string like a base-k number and increments it from right to left. Start from the last position and try increasing the current character. After each increment, check whether it violates the beauty rule (s[i] != s[i-1] and s[i] != s[i-2]). If the character is valid, rebuild the suffix greedily with the smallest valid characters that keep the string beautiful. If no valid increment exists at a position, move left and continue backtracking.
The key insight: once you increase a character at position i, the prefix becomes fixed. The suffix can then be rebuilt with the smallest valid characters to maintain lexicographic minimality. This approach simulates controlled backtracking while preserving the lexicographically smallest valid continuation. It relies heavily on simple character checks and sequential iteration, making it efficient for constraints typically seen in string problems.
Approach 2: Greedy Character Replacement (O(n * k) time, O(1) space)
The greedy strategy scans the string from right to left and attempts to replace each character with the next valid option. For index i, iterate characters from s[i] + 1 to 'a' + k - 1. Choose the first character that doesn't match the previous two characters. Once a valid replacement is found, rebuild the remaining suffix by picking the smallest valid character at each step.
This works because lexicographic order is determined by the earliest differing character. Increasing the rightmost possible index ensures the smallest overall increase. The suffix reconstruction step uses a greedy rule: always choose the smallest character that doesn't conflict with the previous two positions. The approach combines simple iteration with constraints typical in greedy algorithms and local validation rules from string manipulation.
Recommended for interviews: The greedy right-to-left increment approach is what most interviewers expect. It demonstrates understanding of lexicographic ordering, constraint validation, and suffix reconstruction. Mentioning the backtracking interpretation shows deeper reasoning, but implementing the greedy increment + rebuild pattern proves strong problem‑solving skills.
Approach 1: Backtrack and Increment Approach
This approach involves starting from the end of the string and incrementing characters lexicographically. If a valid increment is found, backtrack over the string to ensure no palindromic substrings are formed.
This Python function iterates through the string from right to left, attempting to increment each character while checking if the resultant string remains beautiful. If a valid increment is found at any position, subsequent characters are filled with the smallest lexicographical values permissible to maintain the beauty of the string.
Complexity
Time Complexity: O(n*k)
Space Complexity: O(n)
Approach 2: Greedy Character Replacement
The greedy approach builds the new string from the start, replacing each character with the smallest possible character larger than itself wherever necessary to ensure beauty. If incrementing from a certain point doesn't work, it tries the next character.
This C++ code iterates through the string from the end and tries to replace each character with the next possible lexicographical character, ensuring that it remains a beautiful string by checking against palindromic substrings at each step. Upon success, it greedily fills subsequent characters with the smallest valid characters.
Code
C++
JavaScript
Complexity
Time Complexity: O(n*k)
Space Complexity: O(n)
Approach 3: Greedy
We can find that a palindrome string of length 2 must have two adjacent characters equal; and a palindrome string of length 3 must have two characters at the beginning and end equal. Therefore, a beautiful string does not contain any palindrome substring of length 2 or longer, which means that each character in the string is different from its previous two adjacent characters.
We can greedily search backwards from the last index of the string, find an index i such that the character at index i can be replaced by a slightly larger character, while ensuring that it is different from its two previous adjacent characters.
- If such an index
iis found, then we replaces[i]withc, and replace the characters froms[i+1]tos[n-1]with the characters in the firstkcharacters of the alphabet in the order of the minimum dictionary that are not the same as the previous two adjacent characters. After the replacement is completed, we obtain a beautiful string that is the smallest in the dictionary and greater thans. - If such an index
icannot be found, then we cannot construct a beautiful string greater thansin dictionary order, so return an empty string.
The time complexity is O(n), where n is the length of the string. The space complexity is O(1).
Code
Python
Java
C++
Go
TypeScript
Complexity Comparison
| Approach | Complexity |
|---|---|
| Backtrack and Increment Approach | Time Complexity: O(n*k) |
| Greedy Character Replacement | Time Complexity: O(n*k) |
| Greedy | — |
Detailed Complexity Analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Backtrack and Increment | O(n * k) | O(1) | Useful for understanding the search space and how lexicographic increments propagate when constraints break. |
| Greedy Character Replacement | O(n * k) | O(1) | Preferred solution in interviews. Efficiently finds the next valid string by incrementing from the right and rebuilding the suffix. |
Video Solution
Leetcode Weekly contest 343 - Hard - Lexicographically Smallest Beautiful String • Prakhar Agrawal • 1,358 views views
Watch 5 more video solutions →Frequently Asked Questions
Is Lexicographically Smallest Beautiful String easy or hard?
Lexicographically Smallest Beautiful String Python/Java solution
How to solve Lexicographically Smallest Beautiful String in O(n)?
What is the best approach for Lexicographically Smallest Beautiful String?
Is Lexicographically Smallest Beautiful String asked at Google/Amazon/Meta?
What data structure is used in Lexicographically Smallest Beautiful String?
What is the time complexity of Lexicographically Smallest Beautiful String?
Ready to solve this problem?
Practice Lexicographically Smallest Beautiful String with our built-in code editor and test cases.
Practice on FleetCodeTable of Contents
Practice this problem
Open in Editor