从左往右遍历,尽量把较小的字符放在左边,同时还要注意每个字母只能出现一次,单调栈的思路,或者贪心的思路,有点像:
LeetCode第 402 题:移掉K个数字(C++)_qq_32523711的博客-CSDN博客
这儿并没有真的使用栈,借字符串操作来实现:
如果当前字符的左边字符比当前字符大,而且左边字符在当前字符的右边还会出现,那就先舍弃掉左边字符。
class Solution {
public:
string res = "0";//先加一个0是为了方便判断,类似链表的哑节点
string removeDuplicateLetters(string s) {
int count[26] = {0};//计数器,记录每个字母出现的次数
int visited[26] = {0};//用来记录结果数组里面是否已经包含某个字符,避免重复
for(int i = 0; i < s.size(); ++i) ++count[s[i] - 'a'];
for(const auto &c : s){
--count[c - 'a'];
if(visited[c - 'a'] == 1) continue;//已经包含了
while(c < res.back() && count[res.back() - 'a']){
visited[res.back() - 'a'] = 0;//pop出去就不再包含了
res.pop_back();
}
res += c;
visited[c - 'a'] = 1;//包含了该字符
}
return res.substr(1);
}
};
不加0其实也差不多:
class Solution {
public:
string res;
string removeDuplicateLetters(string s) {
int count[26] = {0};//计数器,记录每个字母出现的次数
int visited[26] = {0};//用来记录结果数组里面是否已经包含某个字符,避免重复
for(int i = 0; i < s.size(); ++i) ++count[s[i] - 'a'];
for(const auto &c : s){
--count[c - 'a'];
if(visited[c - 'a'] == 1) continue;//已经包含了
while(!res.empty() && c < res.back() && count[res.back() - 'a']){
visited[res.back() - 'a'] = 0;//pop出去就不再包含了
res.pop_back();
}
res += c;
visited[c - 'a'] = 1;//包含了该字符
}
return res;
}
};