You are given a string s and an integer k.
Define a function distance(s1, s2) between two strings s1 and s2 of the same length n as:
s1[i] and s2[i] when the characters from 'a' to 'z' are placed in a cyclic order, for all i in the range [0, n - 1].For example, distance("ab", "cd") == 4, and distance("a", "z") == 1.
You can change any letter of s to any other lowercase English letter, any number of times.
Return a string denoting the lexicographically smallest string t you can get after some changes, such that distance(s, t) <= k.
Example 1:
Input: s = "zbbz", k = 3
Output: "aaaz"
Explanation:
Change s to "aaaz". The distance between "zbbz" and "aaaz" is equal to k = 3.
Example 2:
Input: s = "xaxcd", k = 4
Output: "aawcd"
Explanation:
The distance between "xaxcd" and "aawcd" is equal to k = 4.
Example 3:
Input: s = "lol", k = 0
Output: "lol"
Explanation:
It's impossible to change any character as k = 0.
Constraints:
1 <= s.length <= 1000 <= k <= 2000s consists only of lowercase English letters.Problem Overview: You are given a lowercase string s and an integer k. Each operation can shift a character forward or backward in the alphabet with wrap-around (cyclic). The goal is to produce the lexicographically smallest possible string while keeping the total shift cost ≤ k.
Approach 1: Greedy Approach Using Character Replacement (O(n) time, O(1) space)
The key observation is that lexicographic order is determined from left to right. Reducing earlier characters has a much bigger impact than modifying later ones. Iterate through the string and try to convert each character to 'a'. Compute the cyclic distance between the current character and 'a'. If the required cost is ≤ k, convert the character directly to 'a' and subtract that cost from k. If the cost is larger than the remaining budget, reduce the character by exactly k steps toward 'a' and stop further reductions since the budget becomes zero.
This works because any extra reduction on later characters cannot produce a lexicographically smaller result than minimizing earlier characters first. The algorithm performs a single pass through the string and constant-time arithmetic per character, giving O(n) time and O(1) space.
Approach 2: Cyclic Distance and Replacement Strategy (O(n) time, O(1) space)
This approach explicitly models the alphabet as a cycle of size 26. For each character, compute the minimal cyclic distance to 'a' using min(c - 'a', 26 - (c - 'a')). If this minimal distance is within the remaining operation budget, replace the character with 'a'. Otherwise, partially move the character toward 'a' by exactly k positions in the backward direction and terminate since the budget is exhausted.
The cyclic distance calculation is important for cases like 'z', where wrapping forward by one step reaches 'a'. By always selecting the smallest cyclic move that minimizes the character value, the algorithm guarantees the smallest possible prefix at every step. The logic relies on simple arithmetic rather than simulation, which keeps the solution linear.
This problem mainly combines ideas from string manipulation and greedy algorithms. The greedy choice is safe because reducing earlier characters always dominates improvements later in the string.
Recommended for interviews: The greedy single-pass solution is what interviewers expect. A brute-force exploration of possible shifts would be exponential and unnecessary. Showing the greedy reasoning—minimizing each character from left to right while tracking the remaining budget—demonstrates strong understanding of lexicographic ordering and greedy optimization.
In this approach, we aim to replace characters in the given string by rotating towards 'a', as it is the lexicographically smallest character. For each character in the string 's', calculate the minimum distance to 'a' using the cyclic nature of the alphabet. If the distance is within the allowed limit 'k', make the change and reduce 'k' accordingly. The goal is to make the string lexicographically smaller by changing as many characters as possible to 'a'.
The program checks each character to see how far it is from 'a'. If the distance is within 'k', it changes the character to 'a' and reduces 'k'. If the character cannot be changed to 'a' without exceeding 'k', it shifts the character backwards within the limit.
Time Complexity: O(n), where n is the length of the string. Space Complexity: O(1), as the operation is performed in-place.
This alternative approach focuses on leveraging the cyclic nature of the alphabet, considering direct backward shifts within the allowed 'k'. It aims to achieve 'a' replacements as secondary, while possibly transforming non-contiguous characters where allowed for optimal string formation.
The C solution examines character shifts, favoring whole changes to 'a' if possible, otherwise backwards within 'x-a in order to fully utilize 'k'. Early termination occurs if contrary adjustments would exhaust the budget.
Time Complexity: O(n), iterating over the string length. Space Complexity: O(1), made entirely in-place.
We can traverse each position of the string s. For each position, we enumerate all characters less than the current character, calculate the cost d to change to this character. If d leq k, we change the current character to this character, subtract d from k, end the enumeration, and continue to the next position.
After the traversal, we get a string that meets the conditions.
The time complexity is O(n times |\Sigma|), and the space complexity is O(n). Here, n is the length of the string s, and |\Sigma| is the size of the character set. In this problem, |\Sigma| leq 26.
Python
Java
C++
Go
TypeScript
| Approach | Complexity |
|---|---|
| Greedy Approach Using Character Replacement | Time Complexity: O(n), where n is the length of the string. Space Complexity: O(1), as the operation is performed in-place. |
| Cyclic Distance and Replacement Strategy | Time Complexity: O(n), iterating over the string length. Space Complexity: O(1), made entirely in-place. |
| Enumeration | — |
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Greedy Character Replacement | O(n) | O(1) | Best general solution. Minimizes characters from left to right using remaining operation budget. |
| Cyclic Distance Strategy | O(n) | O(1) | Useful when reasoning about alphabet wrap-around and minimal cyclic shifts. |
3106. Lexicographically Smallest String After Operations With Constraint | Adhoc | Strings • Aryan Mittal • 4,375 views views
Watch 9 more video solutions →Practice Lexicographically Smallest String After Operations With Constraint with our built-in code editor and test cases.
Practice on FleetCode