Given a string S consisting of lowercase alphabets, the task is to find the lexicographically smallest string that can be obtained by removing duplicates from the given string S.
Examples:
Input: S = “yzxyz”
Output: xyz
Explanation: Removing the duplicate characters at indices 0 and 1 in the given string, the remaining string “xyz” consists only of unique alphabets only and is the smallest possible string in lexicographical order.Input: S = “acbc”
Output: “abc”
Explanation: Removing the duplicate characters at index 3 in the given string, the remaining string “abc” consists only of unique alphabets only and is the smallest possible string in lexicographical order.
Approach: Follow the steps below to solve the problem:
- Initialize a stack st to store the Lexicographically smallest string, and a visited array vis to find the duplicate letters and map to store the last index of any character.
- Traverse the string and find the last index of every unique character present in the string and store it in the map.
- Traverse the string and if the current character is not seen before, While (stack is not empty and current character < character present at top of the stack and last_index[st.top()]>i)
- then set st.top=0 in vis and pop it from the stack.
- Initialize an empty string, res.
- While the stack is not empty add st.top() in the res then pop it from the stack.
- At last, reverse the string and return it.
Below is the implementation of the above approach:
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;
// Function to remove Duplicate Letters // from string s such that it gives // Lexicographically smallest string string removeDuplicateLetters(string s) { // Stack to store Lexicographically
// smallest string
stack< char > st;
// Visited array to find the
// duplicate letters
vector< int > vis(26, 0);
// Map to store the last index
// of any character
unordered_map< char , int > last_index;
// Size of string S
int n = s.size();
// Find last index of every unique
// character present in the string
for ( int i = 0; i < n; i++) {
last_index[s[i]] = i;
}
// Traverse the string
for ( int i = 0; i < s.length(); i++) {
// Current character
char curr = s[i];
// If curr is not seen before
if (!vis[curr - 'a' ]) {
// While the stack is not empty
// and current character <
// character present at top of
// stack and last_index[st.top()]>i
while (!st.empty() && curr < st.top()
&& last_index[st.top()] > i) {
// Set st.top() = 0 in vis
vis[st.top() - 'a' ] = 0;
// Pop it from stack
st.pop();
}
// Push curr in stack
st.push(curr);
// Set Curr-'a' = 1 in vis
vis[curr - 'a' ] = 1;
}
}
// Initialize a empty string
string res = "" ;
// While stack is not empty
while (!st.empty()) {
res += st.top();
st.pop();
}
// Reverse the string
reverse(res.begin(), res.end());
// return the string
return res;
} // Driver Code int main()
{ string S = "yzxyz" ;
cout << removeDuplicateLetters(S) << endl;
S = "acbc" ;
cout << removeDuplicateLetters(S) << endl;
return 0;
} |
// Java program for the above approach import java.io.*;
import java.util.*;
class GFG {
// Function to remove Duplicate Letters
// from string s such that it gives
// Lexicographically smallest string
static String removeDuplicateLetters(String s)
{
// Stack to store Lexicographically
// smallest string
Stack<Character> st = new Stack<>();
// Visited array to find the
// duplicate letters
int [] vis = new int [ 26 ];
// Map to store the last index
// of any character
Map<Character, Integer> lastIndex = new HashMap<>();
// Size of string S
int n = s.length();
// Find last index of every unique
// character present in the string
for ( int i = 0 ; i < n; i++) {
lastIndex.put(s.charAt(i), i);
}
// Traverse the string
for ( int i = 0 ; i < s.length(); i++) {
// Current character
char curr = s.charAt(i);
// If curr is not seen before
if (vis[curr - 'a' ] == 0 ) {
// While the stack is not empty
// and current character <
// character present at top of
// stack and last_index[st.top()]>i
while (!st.isEmpty() && curr < st.peek()
&& lastIndex.get(st.peek()) > i) {
// Set st.top() = 0 in vis
vis[st.peek() - 'a' ] = 0 ;
// Pop it from stack
st.pop();
}
// Push curr in stack
st.push(curr);
// Set Curr-'a' = 1 in vis
vis[curr - 'a' ] = 1 ;
}
}
// Initialize a empty string
StringBuilder res = new StringBuilder();
// While stack is not empty
while (!st.isEmpty()) {
res.append(st.pop());
}
// Reverse & return the string
return res.reverse().toString();
}
public static void main(String[] args)
{
String S = "yzxyz" ;
System.out.println(removeDuplicateLetters(S));
S = "acbc" ;
System.out.println(removeDuplicateLetters(S));
}
} // This code is contributed by lokesh. |
# C++ program for the above approach # Function to remove Duplicate Letters # from string s such that it gives # Lexicographically smallest string def removeDuplicateLetters(s):
# Stack to store Lexicographically
# smallest string
st = []
# Visited array to find the
# duplicate letters
vis = [ 0 for _ in range ( 26 )]
# Map to store the last index
# of any character
last_index = {}
# Size of string S
n = len (s)
# Find last index of every unique
# character present in the string
for i in range ( 0 , n):
last_index[s[i]] = i
# Traverse the string
for i in range ( 0 , len (s)):
# Current character
curr = s[i]
# If curr is not seen before
if ( not vis[ ord (curr) - ord ( 'a' )]):
# While the stack is not empty
# and current character <
# character present at top of
# stack and last_index[st.top()]>i
while ( len (st) ! = 0 and curr < st[ - 1 ]
and last_index[st[ - 1 ]] > i):
# Set st.top() = 0 in vis
vis[ ord (st[ - 1 ]) - ord ( 'a' )] = 0
# Pop it from stack
st.pop()
# Push curr in stack
st.append(curr)
# Set Curr-'a' = 1 in vis
vis[ ord (curr) - ord ( 'a' )] = 1
# Initialize a empty string
res = ""
# While stack is not empty
while ( len (st) ! = 0 ):
res + = st[ - 1 ]
st.pop()
# Reverse the string
res = res[:: - 1 ]
# return the string
return res
# Driver Code if __name__ = = "__main__" :
S = "yzxyz"
print (removeDuplicateLetters(S))
S = "acbc"
print (removeDuplicateLetters(S))
# This code is contributed by rakeshsahni
|
// JavaScript program for the above approach function removeDuplicateLetters(s) {
// Stack to store Lexicographically
// smallest string
let st = [];
// Visited array to find the
// duplicate letters
let vis = new Array(26).fill(0);
// Map to store the last index
// of any character
let last_index = new Map();
// Size of string S
let n = s.length;
// Find last index of every unique
// character present in the string
for (let i = 0; i < n; i++) {
last_index.set(s[i], i);
}
// Traverse the string
for (let i = 0; i < n; i++) {
// Current character
let curr = s[i];
// If curr is not seen before
if (!vis[curr.charCodeAt(0) - 'a' .charCodeAt(0)]) {
// While the stack is not empty
// and current character <
// character present at top of
// stack and last_index[st.top()]>i
while (st.length !== 0 && curr < st[st.length - 1]
&& last_index.get(st[st.length - 1]) > i) {
// Set st.top() = 0 in vis
vis[st[st.length - 1].charCodeAt(0) - 'a' .charCodeAt(0)] = 0;
// Pop it from stack
st.pop();
}
// Push curr in stack
st.push(curr);
// Set Curr-'a' = 1 in vis
vis[curr.charCodeAt(0) - 'a' .charCodeAt(0)] = 1;
}
}
// Initialize a empty string
let res = "" ;
// While stack is not empty
while (st.length !== 0) {
res += st.pop();
}
// Reverse the string
res = res.split( "" ).reverse().join( "" );
// return the string
return res;
} // Driver Code console.log(removeDuplicateLetters( "yzxyz" ));
console.log(removeDuplicateLetters( "acbc" ));
|
using System;
using System.Collections.Generic;
class Program {
// Function to remove Duplicate Letters
// from string s such that it gives
// Lexicographically smallest string
static string RemoveDuplicateLetters( string s)
{
// Stack to store Lexicographically
// smallest string
Stack< char > st = new Stack< char >();
// Visited array to find the
// duplicate letters
int [] vis = new int [26];
// Map to store the last index
// of any character
Dictionary< char , int > last_index
= new Dictionary< char , int >();
// Size of string S
int n = s.Length;
// Find last index of every unique
// character present in the string
for ( int i = 0; i < n; i++) {
last_index[s[i]] = i;
}
// Traverse the string
for ( int i = 0; i < s.Length; i++) {
// Current character
char curr = s[i];
// If curr is not seen before
if (vis[curr - 'a' ] == 0) {
// While the stack is not empty
// and current character <
// character present at top of
// stack and last_index[st.top()]>i
while (st.Count != 0 && curr < st.Peek()
&& last_index[st.Peek()] > i) {
// Set st.top() = 0 in vis
vis[st.Peek() - 'a' ] = 0;
// Pop it from stack
st.Pop();
}
// Push curr in stack
st.Push(curr);
// Set Curr-'a' = 1 in vis
vis[curr - 'a' ] = 1;
}
}
// Initialize a empty string
string res = "" ;
// While stack is not empty
while (st.Count != 0) {
res += st.Peek();
st.Pop();
}
char [] arr = res.ToCharArray();
// Reverse the string
Array.Reverse(arr);
res = new string (arr);
// return the string
return res;
}
// Driver Code
static void Main( string [] args)
{
string S = "yzxyz" ;
Console.WriteLine(RemoveDuplicateLetters(S));
S = "acbc" ;
Console.WriteLine(RemoveDuplicateLetters(S));
}
} |
xyz abc
Time Complexity: O(N)
Auxiliary Space: O(N)
Related Articles:
- Introduction to String – Data Structures and Algorithms Tutorials
- Introduction to Stack – Data Structures and Algorithms Tutorials