Lexicographically smallest string formed by removing duplicates using stack
Last Updated :
13 Feb, 2023
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++
#include <bits/stdc++.h>
using namespace std;
string removeDuplicateLetters(string s)
{
stack< char > st;
vector< int > vis(26, 0);
unordered_map< char , int > last_index;
int n = s.size();
for ( int i = 0; i < n; i++) {
last_index[s[i]] = i;
}
for ( int i = 0; i < s.length(); i++) {
char curr = s[i];
if (!vis[curr - 'a' ]) {
while (!st.empty() && curr < st.top()
&& last_index[st.top()] > i) {
vis[st.top() - 'a' ] = 0;
st.pop();
}
st.push(curr);
vis[curr - 'a' ] = 1;
}
}
string res = "" ;
while (!st.empty()) {
res += st.top();
st.pop();
}
reverse(res.begin(), res.end());
return res;
}
int main()
{
string S = "yzxyz" ;
cout << removeDuplicateLetters(S) << endl;
S = "acbc" ;
cout << removeDuplicateLetters(S) << endl;
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
static String removeDuplicateLetters(String s)
{
Stack<Character> st = new Stack<>();
int [] vis = new int [ 26 ];
Map<Character, Integer> lastIndex = new HashMap<>();
int n = s.length();
for ( int i = 0 ; i < n; i++) {
lastIndex.put(s.charAt(i), i);
}
for ( int i = 0 ; i < s.length(); i++) {
char curr = s.charAt(i);
if (vis[curr - 'a' ] == 0 ) {
while (!st.isEmpty() && curr < st.peek()
&& lastIndex.get(st.peek()) > i) {
vis[st.peek() - 'a' ] = 0 ;
st.pop();
}
st.push(curr);
vis[curr - 'a' ] = 1 ;
}
}
StringBuilder res = new StringBuilder();
while (!st.isEmpty()) {
res.append(st.pop());
}
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));
}
}
|
Python3
def removeDuplicateLetters(s):
st = []
vis = [ 0 for _ in range ( 26 )]
last_index = {}
n = len (s)
for i in range ( 0 , n):
last_index[s[i]] = i
for i in range ( 0 , len (s)):
curr = s[i]
if ( not vis[ ord (curr) - ord ( 'a' )]):
while ( len (st) ! = 0 and curr < st[ - 1 ]
and last_index[st[ - 1 ]] > i):
vis[ ord (st[ - 1 ]) - ord ( 'a' )] = 0
st.pop()
st.append(curr)
vis[ ord (curr) - ord ( 'a' )] = 1
res = ""
while ( len (st) ! = 0 ):
res + = st[ - 1 ]
st.pop()
res = res[:: - 1 ]
return res
if __name__ = = "__main__" :
S = "yzxyz"
print (removeDuplicateLetters(S))
S = "acbc"
print (removeDuplicateLetters(S))
|
Javascript
function removeDuplicateLetters(s) {
let st = [];
let vis = new Array(26).fill(0);
let last_index = new Map();
let n = s.length;
for (let i = 0; i < n; i++) {
last_index.set(s[i], i);
}
for (let i = 0; i < n; i++) {
let curr = s[i];
if (!vis[curr.charCodeAt(0) - 'a' .charCodeAt(0)]) {
while (st.length !== 0 && curr < st[st.length - 1]
&& last_index.get(st[st.length - 1]) > i) {
vis[st[st.length - 1].charCodeAt(0) - 'a' .charCodeAt(0)] = 0;
st.pop();
}
st.push(curr);
vis[curr.charCodeAt(0) - 'a' .charCodeAt(0)] = 1;
}
}
let res = "" ;
while (st.length !== 0) {
res += st.pop();
}
res = res.split( "" ).reverse().join( "" );
return res;
}
console.log(removeDuplicateLetters( "yzxyz" ));
console.log(removeDuplicateLetters( "acbc" ));
|
C#
using System;
using System.Collections.Generic;
class Program {
static string RemoveDuplicateLetters( string s)
{
Stack< char > st = new Stack< char >();
int [] vis = new int [26];
Dictionary< char , int > last_index
= new Dictionary< char , int >();
int n = s.Length;
for ( int i = 0; i < n; i++) {
last_index[s[i]] = i;
}
for ( int i = 0; i < s.Length; i++) {
char curr = s[i];
if (vis[curr - 'a' ] == 0) {
while (st.Count != 0 && curr < st.Peek()
&& last_index[st.Peek()] > i) {
vis[st.Peek() - 'a' ] = 0;
st.Pop();
}
st.Push(curr);
vis[curr - 'a' ] = 1;
}
}
string res = "" ;
while (st.Count != 0) {
res += st.Peek();
st.Pop();
}
char [] arr = res.ToCharArray();
Array.Reverse(arr);
res = new string (arr);
return res;
}
static void Main( string [] args)
{
string S = "yzxyz" ;
Console.WriteLine(RemoveDuplicateLetters(S));
S = "acbc" ;
Console.WriteLine(RemoveDuplicateLetters(S));
}
}
|
Time Complexity: O(N)
Auxiliary Space: O(N)
Related Articles:
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...