输入:一个字符串s
要求:从字符串s中去除重复的字母,使得每个字母只出现一次。 保证返回结果的字典序最小(要求不能打乱其他字母的相对位置)。
输出:一个只包含s中所有不重复字母的字符串,且字典序最小。
思路:为了确保最终结果的字典序最小,得尽可能让小的字母排在前面。使用一个栈(tmp)来构建最终结果,并配合两个哈希表/数组(outCount 和 inCount)来判定。
复杂度:
时间复杂度:O(n)
空间复杂度:O(n) (最坏O(n))
class Solution {
public:
string removeDuplicateLetters(string s) {
//返回结果字典序最小 也就是开头尽量是最小字符
//两个map<char, int> 一个统计栈外数量 一个统计栈内数量 配合处理
unordered_map<char, int> outCount;
unordered_map<char, int> inCount;
stack<char> tmp;
for (char S:s) {
outCount[S]++;//先统计各字母数量
inCount[S] = 0;
}
//这是从元素值的角度来判定循环 如果是从计数的角度来判定呢
// for (int i = 0; i < s.size(); i++) {
// if (tmp.empty()) {
// tmp.push(s[i]);
// inCount[s[i]]++;
// outCount[s[i]]--;
// }
// else if (s[i] >= tmp.top()) {
// if (inCount[s[i]] == 0) {
// tmp.push(s[i]);
// inCount[s[i]]++;
// outCount[s[i]]--;
// }
// else {
// outCount[s[i]]--;
// }
// }
// else if (s[i] < tmp.top() && inCount[s[i]] == 0) {
// while (!tmp.empty() && outCount[tmp.top()] > 0 && s[i] < tmp.top()) {
// inCount[tmp.top()]--;
// tmp.pop();
// }
// tmp.push(s[i]);
// inCount[s[i]]++;
// outCount[s[i]]--;
// }
// else if (s[i] < tmp.top() && inCount[s[i]] != 0) {
// outCount[s[i]]--;
// }
// }
for (int i = 0; i < s.size(); i++) {
if (inCount[s[i]] == 1) {//栈里有 直接跳过
outCount[s[i]]--;
}
else if (tmp.empty()) {//栈里没有 且 栈空
outCount[s[i]]--;
inCount[s[i]]++;
tmp.push(s[i]);
}
else if (outCount[tmp.top()] == 0) { //栈里没有 栈不空 栈顶元素外面没有 无法弹出 无论是大是小 只能入栈
outCount[s[i]]--;
inCount[s[i]]++;
tmp.push(s[i]);
}
else if (s[i] > tmp.top()) { //栈里没有 栈不空 栈顶元素外面有 比栈顶元素大
outCount[s[i]]--;
inCount[s[i]]++;
tmp.push(s[i]);
}
else if (s[i] < tmp.top()) { //比栈顶元素小 不用考虑相等 第一个inCount[s[i]] == 1就排除相等情况了
inCount[tmp.top()]--;
tmp.pop();
i--;
}
}
string ans;
while (!tmp.empty()) {
ans += tmp.top();
tmp.pop();
}
reverse(ans.begin(), ans.end());
return ans;
}
};
435

被折叠的 条评论
为什么被折叠?



