316. 去除重复字母
题目描述:
给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。
示例 1:
输入:s = "bcabc"输出:"abc"
示例 2:
输入:s = "cbacdcbc"输出:"acdb"
提示:
1 <= s.length <= 10^4s由小写英文字母组成
解题思路:单调栈解法
用一个单调栈维护字典序最小的字符串。由于对每个出现过的字母必须保证出现在最终的字符串中,直接遍历不确定当前出栈的字母后续是否还会出现,需要首先用字典存储每个字母出现的次数,在做出栈操作的时候,若当前字母的剩余出现次数非大于0,则即使不满足单调性该字母也必须进栈。
由于只包含小写字母,因此可以用26大小的vector来存储字母出现的次数,同理需要用一个vis数组保存当前字母是否已经在栈中,若已经在,就不需要重复进栈。
复杂度:由于遍历一遍字符串,且每个字母仅进出栈一次,时间复杂度O(n),空间复杂度:用了栈结构,O(n)
代码:
class Solution {
public:
string removeDuplicateLetters(string s) {
int n = s.length();
if(n <= 1)
return s;
vector<int> flag(26, 0);
vector<int> vis(26, 0);
for(int i=0; i<n; i++) {
flag[s[i]-'a']++;
}
stack<char> mystack;
for(int i=0; i<n; i++) {
while(!mystack.empty() && s[i] < mystack.top() && vis[s[i]-'a'] == 0) {
if(flag[mystack.top()-'a'] > 0) {
vis[mystack.top()-'a'] = 0;
mystack.pop();
} else {
break;
}
}
if(vis[s[i]-'a'] == 0) {
mystack.push(s[i]);
vis[s[i]-'a'] = 1;
}
flag[s[i]-'a']--;
}
string res;
while(!mystack.empty()) {
res += mystack.top();
mystack.pop();
}
reverse(res.begin(), res.end());
return res;
}
};
浙公网安备 33010602011771号