📌  相关文章
📜  通过删除重复项形成的词典上最小的字符串

📅  最后修改于: 2021-04-22 00:08:34             🧑  作者: Mango

给定一个由小写字母组成的字符串S ,任务是找到从字典上最小的字符串,该字符串可以通过从给定字符串S中删除重复项来获得。

例子:

方法:请按照以下步骤解决问题:

  • 初始化字符串res以存储结果字符串。
  • 将给定字符串中存在的每个字符的频率存储在数组freq []中
  • 保持阵列可见光[]用于标记那些已经存在于所得到的字符串RES的字符。
  • 遍历给定的字符串S ,并对每个字符S [i]执行以下操作:
    • 将当前字符的频率降低1
    • 如果当前字符未在数组vis []中标记为已访问,则执行以下操作:
      • 如果res的最后一个字母小于S [i] ,则将S [i]添加到res
      • 如果res的最后一个字母大于S [i]并且res的最后一个字母的计数超过0 ,则删除该字符,并将visit [S [i]]标记为0,然后继续此步骤直到满足上述条件。
      • 从以上条件中突破后,将S [i]添加到res并将标记visit [S [i]]标记为1
  • 完成上述步骤后,将字符串res打印为结果。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function that finds lexicographically
// smallest string after removing the
// duplicates from the given string
string 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 Code
int main()
{
    // Given string S
    string S = "acbc";
 
    // Function Call
    cout << removeDuplicateLetters(S);
 
    return 0;
}


Java
// Java program for the above approach
import java.io.*;
 
class GFG{
 
// Function that finds lexicographically
// smallest string after removing the
// duplicates from the given string
static 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 Code
public 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
# Python3 program for the above approach
 
# Function that finds lexicographically
# smallest after removing the
# duplicates from the given string
def 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 Code
if __name__ == '__main__':
     
    # Given S
    S = "acbc"
 
    # Function Call
    print(removeDuplicateLetters(S))
 
# This code is contributed by mohit kumar 29


C#
// C# program for the above approach
using System;
 
class GFG{
 
// Function that finds lexicographically
// smallest string after removing the
// duplicates from the given string
static 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 Code
public static void Main()
{
     
    // Given string S
    string S = "acbc";
 
    // Function Call
    Console.WriteLine(removeDuplicateLetters(S));
}
}
 
// This code is contributed by akhilsaini


输出:
abc








时间复杂度: O(N)
辅助空间: O(N)