该题思路有两种,一种是将string当做stack处理,另一种是贪婪算法
class Solution {
public:
string removeDuplicateLetters(string s) {
bool inRes[26] = {false};
int counts[26] = {0};
for (auto ch : s) counts[ch - 'a']++;
string res = "";
for (auto ch : s) {
counts[ch - 'a']--;
if (res.empty()) {
res.push_back(ch);
inRes[ch - 'a'] = true;
continue;
}
if (inRes[ch - 'a']) {
continue;
}
while (ch < res.back() && !res.empty() && counts[res.back() - 'a'] > 0) {
inRes[res.back() - 'a'] = false;
res.pop_back();
}
res.push_back(ch);
inRes[ch - 'a'] = true;
}
return res;
}
};
Given the string s, the greedy choice (i.e., the leftmost letter in the answer) is the smallest s[i], s.t. the suffix s[i .. ] contains all the unique letters. (Note that, when there are more than one smallest s[i]'s, we choose the leftmost one. Why? Simply consider the example: "abcacb".)
After determining the greedy choice s[i], we get a new string s' from s by
We then recursively solve the problem w.r.t. s'.
The runtime is O(26 * n) = O(n).
public class Solution {
public String removeDuplicateLetters(String s) {
int[] cnt = new int[26];
int pos = 0; // the position for the smallest s[i]
for (int i = 0; i < s.length(); i++) cnt[s.charAt(i) - 'a']++;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) < s.charAt(pos)) pos = i;
if (--cnt[s.charAt(i) - 'a'] == 0) break;
}
return s.length() == 0 ? "" : s.charAt(pos) + removeDuplicateLetters(s.substring(pos + 1).replaceAll("" + s.charAt(pos), ""));
}
}