「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战」。
题目描述
给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。
示例 1:
输入: s = "bcabc"
输出: "abc"
思路分析
即使是知道这题用单调栈,也很难想到,因为如果是直接用单调栈做的话,应该会在遇到a是弹出cb,当s = “bcab”时就会返回ab,而这个示例的正确输出应该是bca。
所以我们需要保证不弹出相同字母中最后一次出现的字母。可以通过一个数组➕一个map来实现,从后往前遍历字符串,记录每一个字母倒数第几次出现。
具体实现
string removeDuplicateLetters(string s) {
map<char, int> mp;
int len = s.size();
vector<int> arr(len);
stack<int> stk;
string res = "";
for(int i = len - 1; i >= 0; i -- ){
if(mp[s[i]] == 0){
mp[s[i]] = 1;
}else{
mp[s[i]] = mp[s[i]] + 1;
}
arr[i] = mp[s[i]];
}
for(int i = 0; i < len; i++){
while(!stk.empty() && s[i] < s[stk.top()]){
int tmp = stk.top();
if (arr[tmp] == 1){
break;
}
stk.pop();
}
stk.push(i);
}
int k = mp.size();
while(!stk.empty()) {
res = s[stk.top()] + res;
stk.pop();
}
return res.substr(0, k);
}
总结
然而只是过了一半的用例,单调栈加一点灵活的思路是对的,但是不弹出字母最后出现的一次应该是错的,如果按照我的思路,输入为“cdadabcc”应该会输出“adabcc”,正确答案应该是adbc。字母如果已经被使用了,即使不满足单调栈的单调性,也有可能不需要再加进去。因为退栈时最后一次出现的字母是不可以被弹出的。不过因为能力有限,具体条件并没有想出来。留给下期。