Given a string S of N characters, the task is to find the smallest lexicographical string after performing each of the following operations N times in any order:
- Remove the 1st character of S and insert it into a stack X.
- Remove the top of stack X and append it to the end of another string Y which is initially empty.
Example:
Input: S = “cab”
Output: abc
Explanation: The given string can be obtained using the following operations:
- Perform operation 1. Hence, S = “ab”, X = “c”, Y = “”.
- Perform operation 1. Hence, S = “b”, X = “ca”, Y = “”.
- Perform operation 2. Hence, S = “b”, X = “c”, Y = “a”.
- Perform operation 1. Hence, S = “”, X = “cb”, Y = “a”.
- Perform operation 2. Hence, S = “”, X = “c”, Y = “ab”.
- Perform operation 2. Hence, S = “”, X = “”, Y = “abc”.
Now, each of the given operations is performed N times and the string obtained is “abc” which is the smallest possible.
Input: S = “acdb”
Output: abdc
Approach: The given problem can be solved using a greedy approach. The idea is to perform the 1st operation till the top of the stack contains the smallest character after which it can be appended to the string Y. This can be efficiently done by maintaining a suffix array, where suff[i] stores the smallest ASCII value of the suffix till ith character. Below are the steps to follow:
- Traverse the string and create a suffix array suff[] as required.
- If stack X is not empty and suff[i] is greater than equal to top character of stack X, pop the top character of stack X and append it into string Y.
- Else If suff[i] is equal to the S[i] append into string Y.
- Else push character S[i] into the stack X.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
string smallestString(string S)
{
int N = S.size();
int suff[N + 1];
suff[N] = INT_MAX;
for ( int i = N - 1; i >= 0; i--) {
suff[i] = min(suff[i + 1], ( int )S[i]);
}
stack< char > X;
string Y = "" ;
for ( int i = 0; i < N; i++) {
if (X.size() > 0 && suff[i] >= X.top()) {
Y += X.top();
X.pop();
i--;
}
else if (suff[i] == S[i]) {
Y += S[i];
}
else {
X.push(S[i]);
}
}
while (X.size() > 0) {
Y += X.top();
X.pop();
}
return Y;
}
int main()
{
string s = "acdb" ;
cout << smallestString(s);
return 0;
}
|
Java
import java.util.*;
class GFG
{
public static String smallestString(String S)
{
int N = S.length();
int [] suff = new int [N + 1 ];
suff[N] = Integer.MAX_VALUE;
for ( int i = N - 1 ; i >= 0 ; i--) {
suff[i]
= Math.min(suff[i + 1 ], ( int )S.charAt(i));
}
Stack<Character> X = new Stack<Character>();
String Y = "" ;
for ( int i = 0 ; i < N; i++)
{
if (X.size() > 0 && suff[i] >= X.peek()) {
Y += X.peek();
X.pop();
i--;
}
else if (suff[i] == S.charAt(i)) {
Y += S.charAt(i);
}
else {
X.push(S.charAt(i));
}
}
while (X.size() > 0 ) {
Y += X.peek();
X.pop();
}
return Y;
}
public static void main(String[] args)
{
String s = "acdb" ;
System.out.print(smallestString(s));
}
}
|
Python3
import sys
def smallestString(S):
N = len (S)
suff = [ 0 ] * (N + 1 )
suff[N] = sys.maxsize
for i in range (N - 1 , - 2 , - 1 ):
suff[i] = min (suff[i + 1 ], ord (S[i]))
X = []
Y = ""
for i in range ( 0 , N):
if ( len (X) > 0 and suff[i] > = ord (X[ - 1 ])):
Y = Y + X[ - 1 ]
X.pop()
i = i - 1
elif (suff[i] = = ord (S[i])):
Y = Y + S[i]
else :
X.append(S[i])
while ( len (X) > 0 ):
Y = Y + X[ - 1 ]
X.pop()
return Y
s = "acdb"
print (smallestString(s))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
public static String smallestString(String S)
{
int N = S.Length;
int [] suff = new int [N + 1];
suff[N] = int .MaxValue;
for ( int i = N - 1; i >= 0; i--)
{
suff[i]
= Math.Min(suff[i + 1], ( int )S[i]);
}
Stack< char > X = new Stack< char >();
String Y = "" ;
for ( int i = 0; i < N; i++)
{
if (X.Count > 0 && suff[i] >= X.Peek())
{
Y += X.Peek();
X.Pop();
i--;
}
else if (suff[i] == S[i])
{
Y += S[i];
}
else
{
X.Push(S[i]);
}
}
while (X.Count > 0)
{
Y += X.Peek();
X.Pop();
}
return Y;
}
public static void Main()
{
String s = "acdb" ;
Console.Write(smallestString(s));
}
}
|
Javascript
<script>
function smallestString(S) {
let N = S.length;
let suff = new Array(N + 1);
suff[N] = Number.MAX_VALUE;
for (let i = N - 1; i >= 0; i--) {
suff[i] = Math.min(suff[i + 1], S[i].charCodeAt(0));
}
let X = [];
let Y = "" ;
for (let i = 0; i < N; i++) {
if (X.length > 0 && suff[i] >= X[X.length - 1].charCodeAt(0)) {
Y += X[X.length - 1];
X.pop();
i--;
}
else if (String.fromCharCode(suff[i]) == S[i]) {
Y += S[i];
}
else {
X.push(S[i]);
}
}
while (X.length > 0) {
Y += X[X.length - 1];
X.pop();
}
return Y;
}
let s = "acdb" ;
document.write(smallestString(s));
</script>
|
Time Complexity: O(N)
Auxiliary Space: O(N)