Lexicographically smallest string formed by removing duplicates

13 Jun, 2022
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: xyzExplanation: 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 string res to store the resultant string.
Store the frequency of each character present in the given string in an array freq[].
Maintain an array vis[] for marking the characters that are already present in the resultant string res.
Traverse the given string S and for each character S[i], perform the following:Decrease the frequency of the current character by 1.If the current character is not marked visited in the array vis[], then perform the following:If the last letter of res is less than S[i], add S[i] to res.If the last letter of res is greater than S[i] and the count of the last letter of res exceeds 0, then remove that character and mark visit[S[i]] as 0 and continue this step till the above condition is satisfied.After breaking out from the above condition, add S[i] to res and mark visit[S[i]] as 1.
Decrease the frequency of the current character by 1.
If the current character is not marked visited in the array vis[], then perform the following:If the last letter of res is less than S[i], add S[i] to res.If the last letter of res is greater than S[i] and the count of the last letter of res exceeds 0, then remove that character and mark visit[S[i]] as 0 and continue this step till the above condition is satisfied.After breaking out from the above condition, add S[i] to res and mark visit[S[i]] as 1.
If the last letter of res is less than S[i], add S[i] to res.
If the last letter of res is greater than S[i] and the count of the last letter of res exceeds 0, then remove that character and mark visit[S[i]] as 0 and continue this step till the above condition is satisfied.
After breaking out from the above condition, add S[i] to res and mark visit[S[i]] as 1.
After completing the above steps, print the string res as the result.
Below is the implementation of the above approach:
C++
Java
Python3
C#
Javascript
// C++ program for the above approach#include <bits/stdc++.h>using namespace std; // Function that finds lexicographically// smallest string after removing the// duplicates from the given stringstring removeDuplicateLetters(string s){    // Stores the frequency of characters    int cnt[26] = { 0 };     // Mark visited characters    int vis[26] = { 0 };     int n = s.size();     // Stores count of each character    for (int i = 0; i < n; i++)        cnt[s[i] - 'a']++;     // Stores the resultant string    string res = "";     for (int i = 0; i < n; i++) {         // Decrease the count of        // current character        cnt[s[i] - 'a']--;         // If character is not already        // in answer        if (!vis[s[i] - 'a']) {             // Last character > S[i]            // and its count > 0            while (res.size() > 0                   && res.back() > s[i]                   && cnt[res.back() - 'a'] > 0) {                 // Mark letter unvisited                vis[res.back() - 'a'] = 0;                res.pop_back();            }             // Add s[i] in res and            // mark it visited            res += s[i];            vis[s[i] - 'a'] = 1;        }    }     // Return the resultant string    return res;} // Driver Codeint main(){    // Given string S    string S = "acbc";     // Function Call    cout << removeDuplicateLetters(S);     return 0;}
// Java program for the above approachimport java.io.*; class GFG{ // Function that finds lexicographically// smallest string after removing the// duplicates from the given stringstatic String removeDuplicateLetters(String s){         // Stores the frequency of characters    int[] cnt = new int[26];     // Mark visited characters    int[] vis = new int[26];     int n = s.length();     // Stores count of each character    for(int i = 0; i < n; i++)        cnt[s.charAt(i) - 'a']++;     // Stores the resultant string    String res = "";     for(int i = 0; i < n; i++)    {                 // Decrease the count of        // current character        cnt[s.charAt(i) - 'a']--;         // If character is not already        // in answer        if (vis[s.charAt(i) - 'a'] == 0)        {                         // Last character > S[i]            // and its count > 0            int size = res.length();            while (size > 0 &&                   res.charAt(size - 1) > s.charAt(i) &&                   cnt[res.charAt(size - 1) - 'a'] > 0)            {                                 // Mark letter unvisited                vis[res.charAt(size - 1) - 'a'] = 0;                res = res.substring(0, size - 1);                size--;            }                         // Add s[i] in res and            // mark it visited            res += s.charAt(i);            vis[s.charAt(i) - 'a'] = 1;        }    }         // Return the resultant string    return res;} // Driver Codepublic static void main(String[] args){         // Given string S    String S = "acbc";     // Function Call    System.out.println(removeDuplicateLetters(S));}} // This code is contributed by akhilsaini
# Python3 program for the above approach # Function that finds lexicographically# smallest after removing the# duplicates from the given stringdef removeDuplicateLetters(s):         # Stores the frequency of characters    cnt = [0] * 26     # Mark visited characters    vis = [0] * 26     n = len(s)     # Stores count of each character    for i in s:        cnt[ord(i) - ord('a')] += 1     # Stores the resultant string    res = []     for i in range(n):                 # Decrease the count of        # current character        cnt[ord(s[i]) - ord('a')] -= 1         # If character is not already        # in answer        if (not vis[ord(s[i]) - ord('a')]):             # Last character > S[i]            # and its count > 0            while (len(res) > 0 and                    res[-1] > s[i] and           cnt[ord(res[-1]) - ord('a')] > 0):                 # Mark letter unvisited                vis[ord(res[-1]) - ord('a')] = 0                                 del res[-1]             # Add s[i] in res and            # mark it visited            res += s[i]            vis[ord(s[i]) - ord('a')] = 1                 # Return the resultant string    return "".join(res) # Driver Codeif __name__ == '__main__':         # Given S    S = "acbc"     # Function Call    print(removeDuplicateLetters(S)) # This code is contributed by mohit kumar 29
// C# program for the above approachusing System; class GFG{ // Function that finds lexicographically// smallest string after removing the// duplicates from the given stringstatic string removeDuplicateLetters(string s){         // Stores the frequency of characters    int[] cnt = new int[26];         // Mark visited characters    int[] vis = new int[26];     int n = s.Length;     // Stores count of each character    for(int i = 0; i < n; i++)        cnt[s[i] - 'a']++;     // Stores the resultant string    String res = "";     for(int i = 0; i < n; i++)    {                 // Decrease the count of        // current character        cnt[s[i] - 'a']--;         // If character is not already        // in answer        if (vis[s[i] - 'a'] == 0)        {                         // Last character > S[i]            // and its count > 0            int size = res.Length;            while (size > 0 && res[size - 1] > s[i] &&                    cnt[res[size - 1] - 'a'] > 0)            {                                 // Mark letter unvisited                vis[res[size - 1] - 'a'] = 0;                res = res.Substring(0, size - 1);                size--;            }             // Add s[i] in res and            // mark it visited            res += s[i];            vis[s[i] - 'a'] = 1;        }    }     // Return the resultant string    return res;} // Driver Codepublic static void Main(){         // Given string S    string S = "acbc";     // Function Call    Console.WriteLine(removeDuplicateLetters(S));}} // This code is contributed by akhilsaini
<script> // Javascript program for the above approach // Function that finds lexicographically// smallest string after removing the// duplicates from the given stringfunction removeDuplicateLetters(s){    // Stores the frequency of characters    var cnt = Array(26).fill(0);     // Mark visited characters    var vis = Array(26).fill(false);     var n = s.length;     // Stores count of each character    for (var i = 0; i < n; i++)        cnt[s[i].charCodeAt(0) - 'a'.charCodeAt(0)]++;     // Stores the resultant string    var res = "";     for (var i = 0; i < n; i++) {         // Decrease the count of        // current character        cnt[s[i].charCodeAt(0) - 'a'.charCodeAt(0)]--;         // If character is not already        // in answer        if (!vis[s[i].charCodeAt(0) - 'a'.charCodeAt(0)]) {             // Last character > S[i]            // and its count > 0            while (res.length > 0                   && res[res.length-1].charCodeAt(0) >                   s[i].charCodeAt(0)                   && cnt[res[res.length-1].charCodeAt(0) -                   'a'.charCodeAt(0)] > 0) {                 // Mark letter unvisited                vis[res[res.length-1].charCodeAt(0) -                'a'.charCodeAt(0)] = 0;                res = res.substring(0, res.length-1);            }             // Add s[i] in res and            // mark it visited            res += s[i];            vis[s[i].charCodeAt(0) - 'a'.charCodeAt(0)] = 1;        }    }     // Return the resultant string    return res;} // Driver Code// Given string Svar S = "acbc"; // Function Calldocument.write( removeDuplicateLetters(S)); </script>
abc
 
Time Complexity: O(N)Auxiliary Space: O(1) (as we are using visited and cnt both array of fixed size 26)
mohit kumar 29
akhilsaini
itsok
ajaymakvana
frequency-counting
lexicographic-ordering
Greedy
Hash
Strings
Hash
Strings
Greedy
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Huffman Coding | Greedy Algo-3
Coin Change | DP-7
Activity Selection Problem | Greedy Algo-1
Policemen catch thieves
Fractional Knapsack Problem
What is Hashing | A Complete Tutorial
Given an array A[] and a number x, check for pair in A[] with sum as x (aka Two Sum)
Hashing | Set 1 (Introduction)
Internal Working of HashMap in Java
Longest Consecutive Subsequence