Lexicographically Smallest String After Applying Operations solution and explanation
9 more videos on this problem
Leetcode 1625 | Lexicographically Smallest String After Applying Operations | Common Pattern | MIKcodestorywithMIK · 30:48 · 10K views
Leetcode 1625. Lexicographically Smallest String After Applying OperationsFraz · 14:33 · 9K views
LeetCode 1625. Lexicographically Smallest String After Applying OperationsHappy Coding · 12:58 · 2K views
Lexicographically Smallest String After Applying Operations | LeetCode 1625Sanyam IIT Guwahati · 16:42 · 1K views
1625. Lexicographically Smallest String After Applying Operations (Leetcode Medium)Programming Live with Larry · 14:01 · 1K views
1625. Lexicographically Smallest String After Applying Operations | Leetcode Daily - PythonLeetcode Daily · 6:16 · 729 views
Lexicographically Smallest String After Applying Operations | Leetcode 1625 | DSACode with Deepak · 11:43 · 718 views
Leetcode Solutions 1625. Lexicographically Smallest String After Applying OperationsAbrar & Software Engineering · 6:29 · 703 views
Lexicographically Smallest String After Applying Operations | LeetCode 1625 - Pythonimpoldev · 9:41 · 341 views
1625. Lexicographically Smallest String After Applying Operations | Leetcode Daily Challenge | BFSEye on AI and DSA · 17:35 · 199 views
The problem
You are given a string s of even length consisting of digits from 0 to 9, and two integers a and b.
You can apply either of the following two operations any number of times and in any order on s:
- Add
ato all odd indices ofs(0-indexed). Digits post9are cycled back to0. For example, ifs = "3456"anda = 5,sbecomes"3951". - Rotate
sto the right bybpositions. For example, ifs = "3456"andb = 1,sbecomes"6345".
Return the lexicographically smallest string you can obtain by applying the above operations any number of times on s.
A string a is lexicographically smaller than a string b (of the same length) if in the first position where a and b differ, string a has a letter that appears earlier in the alphabet than the corresponding letter in b. For example, "0158" is lexicographically smaller than "0190" because the first position they differ is at the third letter, and '5' comes before '9'.
Example 1:
Input: s = "5525", a = 9, b = 2 Output: "2050" Explanation: We can apply the following operations: Start: "5525" Rotate: "2555" Add: "2454" Add: "2353" Rotate: "5323" Add: "5222" Add: "5121" Rotate: "2151" Add: "2050" There is no way to obtain a string that is lexicographically smaller than "2050".
Example 2:
Input: s = "74", a = 5, b = 1 Output: "24" Explanation: We can apply the following operations: Start: "74" Rotate: "47" Add: "42" Rotate: "24" There is no way to obtain a string that is lexicographically smaller than "24".
Example 3:
Input: s = "0011", a = 4, b = 2 Output: "0011" Explanation: There are no sequence of operations that will give us a lexicographically smaller string than "0011".
Constraints:
2 <= s.length <= 100s.lengthis even.sconsists of digits from0to9only.1 <= a <= 91 <= b <= s.length - 1
Approach overview
Problem Overview: You start with a numeric string s. Two operations are allowed: add a to every digit at odd indices (mod 10), or rotate the string to the right by b positions. Apply any sequence of operations and return the lexicographically smallest string you can produce.
Approach 1: Brute Force with BFS to Check All Combinations (Time: O(K * n), Space: O(K * n))
Model the problem as a state graph where each node is a string configuration. From a state, generate two neighbors: one after applying the add operation and one after the rotate operation. Use Breadth-First Search with a visited set to avoid revisiting the same string. While exploring states, keep track of the lexicographically smallest string encountered. If K is the number of reachable configurations, BFS processes each once and each operation costs O(n) for string transformation.
The key insight is that operations form cycles. Digits wrap around modulo 10 and rotations eventually repeat, so the reachable state space is finite. BFS guarantees you enumerate every valid configuration without duplicates. This approach is straightforward and reliable for typical constraints.
Approach 2: Mathematical Cycle Detection to Minimize Operations (Time: O(n * 10 * (n / gcd(n, b))), Space: O(1))
The operations follow predictable cycles. Rotating by b repeatedly only produces n / gcd(n, b) unique rotations. Similarly, repeatedly adding a to digits cycles every 10 operations because digits are modulo 10. Instead of exploring a graph, iterate through all possible rotation states and simulate addition cycles on odd indices (and even indices when rotation changes parity).
For each rotation, try all possible additions (at most 10) to minimize digits at odd positions. If rotation allows even positions to be affected, apply addition cycles there as well. Build the candidate string and track the smallest lexicographic result. This turns the search into controlled enumeration over small mathematical cycles instead of an unbounded traversal.
The logic relies on modular arithmetic properties of digit addition and rotation parity. You still explore all reachable outcomes, but without storing every intermediate state. The approach combines string manipulation with careful enumeration patterns often seen in DFS style state exploration problems.
Recommended for interviews: Start with the BFS state exploration. It clearly models the problem as a graph and demonstrates understanding of visited-state pruning. After that, discuss the mathematical cycle optimization. Interviewers often appreciate recognizing that rotations and digit additions repeat in predictable cycles, reducing the search space significantly.
Approach 1: Brute Force with BFS to Check All Combinations
This approach leverages a breadth-first search (BFS) to explore all possible string configurations by applying the given operations. We keep track of already-visited states to avoid processing them again, storing the lexicographically smallest string found in the process.
The key point is to simulate the effect of each operation (addition and rotation) and use a queue to handle the states and explore until no new configurations can be found.
from collections import deque
def find_lex_smallest_string(s, a, b):
def add_to_odd_indices(s, a):
result = list(s)
for i in range(1, len(s), 2):
result[i] = str((int(result[i]) + a) % 10)
return ''.join(result)
def rotate_right(s, b):
return s[-b:] + s[:-b]
visited = set()
queue = deque([s])
smallest = s
while queue:
current = queue.popleft()
if current < smallest:
smallest = current
added = add_to_odd_indices(current, a)
rotated = rotate_right(current, b)
for new_s in [added, rotated]:
if new_s not in visited:
visited.add(new_s)
queue.append(new_s)
return smallest
s = "5525"
a = 9
b = 2
print(find_lex_smallest_string(s, a, b)) # Output: "2050"import java.util.*;
public class Solution {
private static String addToOddIndices(String s, int a) {
char[] result = s.toCharArray();
for (int i = 1; i < s.length(); i += 2) {
result[i] = (char) (((result[i] - '0' + a) % 10) + '0');
}
return new String(result);
}
private static String rotateRight(String s, int b) {
int n = s.length();
return s.substring(n - b) + s.substring(0, n - b);
}
public static String findLexSmallestString(String s, int a, int b) {
Set<String> visited = new HashSet<>();
Queue<String> queue = new LinkedList<>();
String smallest = s;
queue.offer(s);
visited.add(s);
while (!queue.isEmpty()) {
String current = queue.poll();
if (current.compareTo(smallest) < 0) smallest = current;
String added = addToOddIndices(current, a);
if (!visited.contains(added)) {
visited.add(added);
queue.offer(added);
}
String rotated = rotateRight(current, b);
if (!visited.contains(rotated)) {
visited.add(rotated);
queue.offer(rotated);
}
}
return smallest;
}
public static void main(String[] args) {
System.out.println(findLexSmallestString("5525", 9, 2)); // Output: "2050"
}
}#include <iostream>
#include <string>
#include <queue>
#include <unordered_set>
using namespace std;
string addToOddIndices(const string& s, int a) {
string result = s;
for (int i = 1; i < s.size(); i += 2) {
result[i] = '0' + (result[i] - '0' + a) % 10;
}
return result;
}
string rotateRight(const string& s, int b) {
int n = s.size();
return s.substr(n - b) + s.substr(0, n - b);
}
string findLexSmallestString(string s, int a, int b) {
unordered_set<string> visited;
queue<string> q;
string smallest = s;
q.push(s);
visited.insert(s);
while (!q.empty()) {
string current = q.front(); q.pop();
if (current < smallest) smallest = current;
// Add to odd indices
string added = addToOddIndices(current, a);
if (visited.find(added) == visited.end()) {
visited.insert(added);
q.push(added);
}
// Rotate right by b
string rotated = rotateRight(current, b);
if (visited.find(rotated) == visited.end()) {
visited.insert(rotated);
q.push(rotated);
}
}
return smallest;
}
int main() {
cout << findLexSmallestString("5525", 9, 2) << endl; // Output: "2050"
return 0;
}function addToOddIndices(s, a) {
let result = s.split("");
for (let i = 1; i < s.length; i += 2) {
result[i] = ((parseInt(result[i]) + a) % 10).toString();
}
return result.join("");
}
function rotateRight(s, b) {
return s.slice(-b) + s.slice(0, -b);
}
function findLexSmallestString(s, a, b) {
let visited = new Set();
let queue = [s];
let smallest = s;
while (queue.length) {
let current = queue.shift();
if (current < smallest) smallest = current;
let added = addToOddIndices(current, a);
let rotated = rotateRight(current, b);
if (!visited.has(added)) {
visited.add(added);
queue.push(added);
}
if (!visited.has(rotated)) {
visited.add(rotated);
queue.push(rotated);
}
}
return smallest;
}
console.log(findLexSmallestString("5525", 9, 2)); // Output: "2050";using System;
using System.Collections.Generic;
public class Solution {
private static string AddToOddIndices(string s, int a) {
char[] result = s.ToCharArray();
for (int i = 1; i < s.Length; i += 2) {
result[i] = (char)(((result[i] - '0' + a) % 10) + '0');
}
return new string(result);
}
private static string RotateRight(string s, int b) {
int n = s.Length;
return s.Substring(n - b) + s.Substring(0, n - b);
}
public static string FindLexSmallestString(string s, int a, int b) {
HashSet<string> visited = new HashSet<string>();
Queue<string> queue = new Queue<string>();
string smallest = s;
queue.Enqueue(s);
visited.Add(s);
while (queue.Count > 0) {
string current = queue.Dequeue();
if (string.Compare(current, smallest) < 0) smallest = current;
string added = AddToOddIndices(current, a);
if (!visited.Contains(added)) {
visited.Add(added);
queue.Enqueue(added);
}
string rotated = RotateRight(current, b);
if (!visited.Contains(rotated)) {
visited.Add(rotated);
queue.Enqueue(rotated);
}
}
return smallest;
}
public static void Main() {
Console.WriteLine(FindLexSmallestString("5525", 9, 2)); // Output: "2050"
}
}The Python solution uses BFS to explore each possible configuration of the string obtained by performing the operations. Starting from the initial string, it performs an addition operation and a rotation operation, pushing these new strings to the queue to be evaluated later, ensuring that each configuration is only visited once by using a set.
Time Complexity: O(n * 10 * n), where n is the length of the string, as the cycle for each index via addition is at most 10, and there are n possible configurations for rotations.
Space Complexity: O(n * n) for storing possible configurations in the 'visited' set.
Approach 2: Mathematical Cycle Detection to Minimize Operations
This approach reduces complexity by detecting cycles in possible configurations without exhausting all possibilities. It leverages mathematical principles governing rotations and additions, where applying operationsform sequences and constraints that can terminate the search early once a smallest string is identified.
By identifying recurring patterns in transformation sequences, computational resources can be conserved, and optimizations applied, particularly in identifying redundant operations that do not lead to smaller strings.
def find_lex_smallest_string_math(s, a, b):
from itertools import combinations
def add_to_odd_indices(s, a):
return ''.join((chr((ord(c) - ord('0') + (a if i % 2 else 0)) % 10 + ord('0')) if i % 2 else c) for i, c in enumerate(s))
def get_rotations(s, b):
n = len(s)
rotations = [s]
for i in range(n):
s = s[-b:] + s[:-b]
rotations.append(s)
return rotations
smallest = s
visited = set()
for add_count in range(10):
modified = s
for _ in range(add_count):
modified = add_to_odd_indices(modified, a)
for rotation in get_rotations(modified, b):
if rotation not in visited and rotation < smallest:
smallest = rotation
visited.add(rotation)
return smallest
s = "5525"
a = 9
b = 2
print(find_lex_smallest_string_math(s, a, b)) # Output: "2050"This Python code reduces operations by recognizing cycles in resulting transformations the operations can achieve. It systematically applies a limited number of additions and explores all rotations, using combinations to ensure minimal complexity is faced.
Time Complexity: O(10 * n^2), reduced due to early detection of cycles and constraints on possibilities given operation properties.
Space Complexity: O(n).
Approach 3: BFS
Since the data scale of this problem is relatively small, we can use BFS to brute-force search all possible states and then take the lexicographically smallest state.
function findLexSmallestString(s: string, a: number, b: number): string {
const q: string[] = [s];
const vis = new Set<string>([s]);
let ans = s;
let i = 0;
while (i < q.length) {
s = q[i++];
if (ans > s) {
ans = s;
}
const t1 = s
.split('')
.map((c, j) => (j & 1 ? String((Number(c) + a) % 10) : c))
.join('');
const t2 = s.slice(-b) + s.slice(0, -b);
for (const t of [t1, t2]) {
if (!vis.has(t)) {
vis.add(t);
q.push(t);
}
}
}
return ans;
}func findLexSmallestString(s string, a int, b int) string {
q := []string{s}
vis := map[string]bool{s: true}
ans := s
n := len(s)
for len(q) > 0 {
s = q[0]
q = q[1:]
if ans > s {
ans = s
}
t1 := []byte(s)
for i := 1; i < n; i += 2 {
t1[i] = byte((int(t1[i]-'0')+a)%10 + '0')
}
t2 := s[n-b:] + s[:n-b]
for _, t := range []string{string(t1), t2} {
if !vis[t] {
vis[t] = true
q = append(q, t)
}
}
}
return ans
}Approach 4: Enumeration
We observe that for the addition operation, a digit will return to its original state after at most 10 additions; for the rotation operation, the string will also return to its original state after at most n rotations.
Therefore, the rotation operation produces at most n states. If the rotation count b is even, the addition operation only affects digits at odd indices, resulting in a total of n times 10 states; if the rotation count b is odd, the addition operation affects both odd and even index digits, resulting in a total of n times 10 times 10 states.
Thus, we can directly enumerate all possible string states and take the lexicographically smallest one.
The time complexity is O(n^2 times 10^2) and the space complexity is O(n), where n is the length of string s.
function findLexSmallestString(s: string, a: number, b: number): string {
let ans = s;
const n = s.length;
let arr = s.split('');
for (let _ = 0; _ < n; _++) {
arr = arr.slice(-b).concat(arr.slice(0, -b));
for (let j = 0; j < 10; j++) {
for (let k = 1; k < n; k += 2) {
arr[k] = String((Number(arr[k]) + a) % 10);
}
if (b & 1) {
for (let p = 0; p < 10; p++) {
for (let k = 0; k < n; k += 2) {
arr[k] = String((Number(arr[k]) + a) % 10);
}
const t = arr.join('');
if (ans > t) {
ans = t;
}
}
} else {
const t = arr.join('');
if (ans > t) {
ans = t;
}
}
}
}
return ans;
}func findLexSmallestString(s string, a int, b int) string {
n := len(s)
ans := s
for _ = range s {
s = s[n-b:] + s[:n-b]
cs := []byte(s)
for j := 0; j < 10; j++ {
for k := 1; k < n; k += 2 {
cs[k] = byte((int(cs[k]-'0')+a)%10 + '0')
}
if b&1 == 1 {
for p := 0; p < 10; p++ {
for k := 0; k < n; k += 2 {
cs[k] = byte((int(cs[k]-'0')+a)%10 + '0')
}
s = string(cs)
if ans > s {
ans = s
}
}
} else {
s = string(cs)
if ans > s {
ans = s
}
}
}
}
return ans
}Complexity comparison
| Approach | Complexity |
|---|---|
| Brute Force with BFS to Check All Combinations | Time Complexity: O(n * 10 * n), where n is the length of the string, as the cycle for each index via addition is at most 10, and there are n possible configurations for rotations. Space Complexity: O(n * n) for storing possible configurations in the 'visited' set. |
| Mathematical Cycle Detection to Minimize Operations | Time Complexity: O(10 * n^2), reduced due to early detection of cycles and constraints on possibilities given operation properties. Space Complexity: O(n). |
| BFS | – |
| Enumeration | – |
Complexity analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Brute Force BFS State Exploration | O(K * n) | O(K * n) | General solution when modeling operations as a graph of states |
| Mathematical Cycle Enumeration | O(n * 10 * (n / gcd(n,b))) | O(1) | When recognizing rotation and addition cycles to avoid full graph traversal |
Frequently asked questions
Is Lexicographically Smallest String After Applying Operations easy or hard?
This problem is typically rated Medium difficulty. The challenge is recognizing that operations form cycles and avoiding infinite exploration. Once modeled as a finite state graph with BFS or cycle enumeration, the implementation becomes manageable.
Lexicographically Smallest String After Applying Operations Python/Java solution
Python and Java implementations usually follow the BFS state exploration strategy. Use a queue to process strings, generate the two possible next states, and track visited states with a set. The smallest lexicographic string encountered during traversal is returned as the final answer.
How to solve Lexicographically Smallest String After Applying Operations in O(n)?
A near-linear solution relies on cycle detection using modular arithmetic. Rotations repeat after n / gcd(n, b) steps and digit additions repeat every 10 operations due to modulo 10. Enumerating these cycles lets you test all valid configurations without storing every state explicitly.
What is the best approach for Lexicographically Smallest String After Applying Operations?
Breadth-First Search over string states is the most common approach. Treat each string as a node and generate neighbors by applying the add and rotate operations. Track visited states to avoid repetition and update the smallest lexicographic string during traversal. Time complexity is O(K * n) where K is the number of reachable configurations.
Is Lexicographically Smallest String After Applying Operations asked at Google/Amazon/Meta?
Variants of this problem appear in interviews at companies like Amazon and Google because it combines string manipulation with state-space search. Interviewers often expect candidates to model operations as graph transitions and use BFS or reasoning about cycles.
What data structure is used in Lexicographically Smallest String After Applying Operations?
The BFS solution primarily uses a queue for traversal and a hash set to track visited strings. These structures prevent revisiting states and ensure each configuration is processed once. String manipulation is used to apply digit addition and rotation operations.
What is the time complexity of Lexicographically Smallest String After Applying Operations?
The BFS approach runs in O(K * n) time where K is the number of reachable string states and n is the string length. Each state requires O(n) time to apply the add or rotate operation. A mathematical cycle optimization reduces exploration to O(n * 10 * (n / gcd(n, b))).
