Given a string which contains only lowercase letters, remove duplicate letters so that every letter appear once and only once. You must make sure your result is the smallest in lexicographical order among all possible results.
Example:
Given "bcabc"
Return "abc"
Given "cbacdcbc"
Return "acdb"
class Solution {
public:
/*algorithm: greedy
idea:
1)based on lexi order,search s, find min char c in S, after c, it should include other chars,we use count[i] to track this
2)S=S.substr(i+1), and remove same char c ,from S
3)repeat the process until S is empty
time O(n*k)
"bcabc"
*/
string removeDuplicateLetters(string s) {
if(s.size() < 2)return s;
string ret;
unordered_set<char>cache;
vector<int>count(s.size(),0);
//build count array
for(int i = int(s.size())-1;i >= 0;i--){
cache.insert(s[i]);
count[i] = cache.size();
}
//select min
int mId = 0;
for(int i = 1;i < count.size() && count[i] >= count[0];i++){
if(s[mId] > s[i])mId = i;
}
ret = ret + s[mId];
for(int i = mId+1;i < s.size();){
if(s[i]==s[mId])s.erase(s.begin()+i);
else i++;
}
return ret + removeDuplicateLetters(s.substr(mId+1));
}
};
class Solution {
public:
/*algorithm: stack+greedy
idea:
1)one array to track the occurence of each char, one array to track visited or so
2)scan from string begin to end
if s[i] < res[last], pop res until res[last] < s[i]
push s[i] to res
3) res is the result
time O(n)
*/
string removeDuplicateLetters(string s) {
int m[256] = {0}, visited[256] = {0};
char res[27]={'\0'};
int last = -1;
for (int i = 0;i < s.size();i++) ++m[s[i]];
for (int i = 0;i < s.size();i++) {
--m[s[i]];
if (visited[s[i]]) continue;
while (last >= 0 && s[i] < res[last] && m[res[last]]) {
visited[res[last]] = 0;
last--;
}
res[++last]=s[i];
visited[s[i]] = 1;
}
res[last+1]='\0';
return res;
}
};