题目:3170. 删除星号以后字典序最小的字符串
方法一:题意就是希望遇到字符时,可以将最近的字典序最小的字符去掉。我们用一个优先队列来记录除之外的字符,并将其按题意要求排好序,这样遇到*时,直接将队列最前面的字符去掉即可。时间复杂度为0(nlogn),细节看注释
class Solution {
public:
typedef struct Node{
char c;
int id;
//按题意,构造排序
friend bool operator<(struct Node t1,struct Node t2){
if(t1.c==t2.c) return t1.id<t2.id;
return t1.c>t2.c;
}
}node;
string clearStars(string s) {
int n=s.size();
//标记哪些字符需要留下
vector<bool> sta(n,1);
//优先队列
priority_queue<node> qu;
for(int i=0;i<n;i++){
if(s[i]!='*') qu.push({s[i],i});
else{
sta[i]=0;
node tmp=qu.top();
qu.pop();
sta[tmp.id]=0;
}
}
//将剩下的字符输出即可
string ed="";
for(int i=0;i<n;i++){
if(sta[i]) ed.push_back(s[i]);
}
return ed;
}
};
方法二:我们也可以构造26个字母的栈,在遇到字符*时,直接按顺序对第一个不为空的栈操作就行。
class Solution {
public:
string clearStars(string s) {
int n=s.size();
//标记哪些字符需要留下
vector<bool> sta(n,1);
//26个字母的栈
vector<int> v[26];
for(int i=0;i<n;i++){
//遇到字符*时
if(s[i]=='*'){
//按顺序对第一个不为空的栈操作
for(auto & x:v){
if(!x.empty()){
sta[x.back()]=0;
x.pop_back();
break;
}
}
sta[i]=0;
}else{
v[s[i]-'a'].push_back(i);
}
}
string ed="";
for(int i=0;i<n;i++){
if(sta[i]) ed.push_back(s[i]);
}
return ed;
}
};