给定一个由小写字母组成的字符串S ,任务是找到从字典上最小的字符串,该字符串可以通过从给定字符串S中删除重复项来获得。
例子:
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.
方法:请按照以下步骤解决问题:
- 初始化字符串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)