仅包含一次所有不同字符的字典序最大子序列
给定一个字符串S ,任务是从给定的字符串中找出所有不同字符只能由一次构成的字典序上最大的子序列。
例子:
Input: S = ababc
Output: bac
Explanation:
All possible subsequences containing all the characters in S exactly once are {“abc”, “bac”}. The lexicograohically maximum among all the subsequences is “bac”.
Input: S = “zydsbacab”
Output: zydscab
方法:给定的问题可以使用Stack来解决。这个想法是遍历字符串并将这些字符以字典顺序最大的顺序存储在堆栈中,以便生成结果字符串。请按照以下步骤解决给定的问题:
- 将字符串S的所有字符的频率存储在一个数组中,比如count[] 。
- 初始化一个数组,比如visited[] ,它存储堆栈中是否存在任何字符。
- 使用变量i遍历给定的字符串S并执行以下步骤:
- 将数组count[]中字符S[i]的频率减少1 。
- 现在,如果字符已经存在于堆栈中,则继续下一次迭代。
- 否则,检查当前字符是否大于栈顶字符且栈顶字符出现的频率是否大于0 ,然后继续从栈中弹出栈顶元素。
- 完成上述步骤后,在数组visited[]中添加当前字符并将其标记为已访问。
- 完成上述步骤后,使用堆栈中的字符生成字符串并打印它的反向以获得字典上最大的子序列。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find the lexicographically
// largest subsequence consisting of all
// distinct characters of S only once
string lexicoMaxSubsequence(string s, int n)
{
stack st;
// Stores if any alphabet is present
// in the current stack
vector visited(26, 0), cnt(26, 0);
// Findthe number of occurences of
// the character s[i]
for (int i = 0; i < n; i++) {
cnt[s[i] - 'a']++;
}
for (int i = 0; i < n; i++) {
// Decrease the character count
// in remaining string
cnt[s[i] - 'a']--;
// If character is already present
// in the stack
if (visited[s[i] - 'a']) {
continue;
}
// if current character is greater
// than last character in stack
// then pop the top character
while (!st.empty() && st.top() < s[i]
&& cnt[st.top() - 'a'] != 0) {
visited[st.top() - 'a'] = 0;
st.pop();
}
// Push the current character
st.push(s[i]);
visited[s[i] - 'a'] = 1;
}
// Stores the resultant string
string s1;
// Generate the string
while (!st.empty()) {
s1 = st.top() + s1;
st.pop();
}
// Return the resultant string
return s1;
}
// Driver Code
int main()
{
string S = "ababc";
int N = S.length();
cout << lexicoMaxSubsequence(S, N);
return 0;
}
Java
/*package whatever //do not write package name here */
import java.io.*;
import java.util.*;
class GFG {
// Function to find the lexicographically
// largest subsequence consisting of all
// distinct characters of S only once
static String lexicoMaxSubsequence(String s, int n)
{
Stack st = new Stack();
// Stores if any alphabet is present
// in the current stack
int[] visited = new int[26];
int[] cnt = new int[26];
for (int i = 0; i < 26; i++) {
visited[i] = 0;
cnt[i] = 0;
}
// Findthe number of occurences of
// the character s[i]
for (int i = 0; i < n; i++) {
cnt[s.charAt(i) - 'a']++;
}
for (int i = 0; i < n; i++) {
// Decrease the character count
// in remaining string
cnt[s.charAt(i) - 'a']--;
// If character is already present
// in the stack
if (visited[s.charAt(i) - 'a'] > 0) {
continue;
}
// if current character is greater
// than last character in stack
// then pop the top character
while (!st.empty() && st.peek() < s.charAt(i)
&& cnt[st.peek() - 'a'] != 0) {
visited[st.peek() - 'a'] = 0;
st.pop();
}
// Push the current character
st.push(s.charAt(i));
visited[s.charAt(i) - 'a'] = 1;
}
// Stores the resultant string
String s1 = "";
// Generate the string
while (!st.empty()) {
s1 = st.peek() + s1;
st.pop();
}
// Return the resultant string
return s1;
}
// Driver Code
public static void main(String[] args)
{
String S = "ababc";
int N = S.length();
System.out.println(lexicoMaxSubsequence(S, N));
}
}
// This code is contributed by maddler.
Python3
# Python3 program for the above approach
# Function to find the lexicographically
# largest subsequence consisting of all
# distinct characters of S only once
def lexicoMaxSubsequence(s, n):
st = []
# Stores if any alphabet is present
# in the current stack
visited = [0]*(26)
cnt = [0]*(26)
for i in range(26):
visited[i] = 0
cnt[i] = 0
# Findthe number of occurences of
# the character s[i]
for i in range(n):
cnt[ord(s[i]) - ord('a')]+=1
for i in range(n):
# Decrease the character count
# in remaining string
cnt[ord(s[i]) - ord('a')]-=1
# If character is already present
# in the stack
if (visited[ord(s[i]) - ord('a')] > 0):
continue
# if current character is greater
# than last character in stack
# then pop the top character
while (len(st) > 0 and ord(st[-1]) < ord(s[i]) and cnt[ord(st[-1]) - ord('a')] != 0):
visited[ord(st[-1]) - ord('a')] = 0
st.pop()
# Push the current character
st.append(s[i])
visited[ord(s[i]) - ord('a')] = 1
# Stores the resultant string
s1 = ""
# Generate the string
while (len(st) > 0):
s1 = st[-1] + s1
st.pop()
# Return the resultant string
return s1
S = "ababc"
N = len(S)
print(lexicoMaxSubsequence(S, N))
# This code is contributed by decode2207.
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG {
// Function to find the lexicographically
// largest subsequence consisting of all
// distinct characters of S only once
static string lexicoMaxSubsequence(string s, int n)
{
Stack st = new Stack();
// Stores if any alphabet is present
// in the current stack
int[] visited = new int[26];
int[] cnt = new int[26];
for (int i = 0; i < 26; i++) {
visited[i] = 0;
cnt[i] = 0;
}
// Findthe number of occurences of
// the character s[i]
for (int i = 0; i < n; i++) {
cnt[s[i] - 'a']++;
}
for (int i = 0; i < n; i++) {
// Decrease the character count
// in remaining string
cnt[s[i] - 'a']--;
// If character is already present
// in the stack
if (visited[s[i] - 'a'] > 0) {
continue;
}
// if current character is greater
// than last character in stack
// then pop the top character
while (st.Count > 0 && st.Peek() < s[i]
&& cnt[st.Peek() - 'a'] != 0) {
visited[st.Peek() - 'a'] = 0;
st.Pop();
}
// Push the current character
st.Push(s[i]);
visited[s[i] - 'a'] = 1;
}
// Stores the resultant string
string s1 = "";
// Generate the string
while (st.Count > 0) {
s1 = st.Peek() + s1;
st.Pop();
}
// Return the resultant string
return s1;
}
static void Main() {
string S = "ababc";
int N = S.Length;
Console.Write(lexicoMaxSubsequence(S, N));
}
}
// This code is contributed by suresh07.
Javascript
输出:
bac
时间复杂度: O(N)
辅助空间: O(N)