Lexicographically smallest string formed by removing duplicates using stack
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++
// 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
// 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. |
Python3
# 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
// 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" )); |
C#
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
Please Login to comment...