Remove Duplicate Letters
Link
Description
Given a string s
, remove duplicate letters so that every letter appears once and only once. You must make sure your result is the smallest in lexicographical order among all possible results.
A string a
is lexicographically smaller than a string b
if in the first position where a
and b
differ, string a
has a letter that appears earlier in the alphabet than the corresponding letter in b
.
If the first min(a.length, b.length)
characters do not differ, then the shorter string is the lexicographically smaller one.
Example 1:
- Input:
s = "bcabc"
- Output:
"abc"
Example 2:
- Input:
s = "cbacdcbc"
- Output:
"acdb"
Constraints:
1 <= s.length <= 10^4
s
consists of lowercase English letters.
Solution
| class Solution {
public:
string removeDuplicateLetters(string s) {
const int MAXN = 26;
vector<int> cnts(MAXN, 0);
vector<bool> enter(MAXN, false);
stack<char> stk;
for (char ch : s) {
cnts[ch - 'a']++;
}
for (char ch : s) {
if (!enter[ch - 'a']) {
while (!stk.empty() && stk.top() > ch && cnts[stk.top() - 'a'] > 0) {
enter[stk.top() - 'a'] = false;
stk.pop();
}
stk.push(ch);
enter[ch - 'a'] = true;
}
cnts[ch - 'a']--;
}
string res = "";
while (!stk.empty()) {
res += stk.top();
stk.pop();
}
reverse(res.begin(), res.end());
return res;
}
};
|
Better way of writing:
| class Solution {
public:
string removeDuplicateLetters(string s) {
string stk;
unordered_map<char, bool> enter;
unordered_map<char, int> last;
for (int i = 0; i < s.size(); i++) {
last[s[i]] = i;
}
for (int i = 0; i < s.size(); i++) {
if (enter[s[i]]) continue;
while (!stk.empty() && stk.back() > s[i] && last[stk.back()] > i) {
enter[stk.back()] = false;
stk.pop_back();
}
stk += s[i];
enter[s[i]] = true;
}
return stk;
}
};
|
- Time complexity: \(O(n)\);
- (Extra) space complexity: \(O(1)\).