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.
Example 1:
Input: s = "bcabc"
Output: "abc"
Example 2:
Input: s = "cbacdcbc"
Output: "acdb"
Constraints:
1 <= s.length <= 104
s
consists of lowercase English letters.
Note: This question is the same as 1081: https://leetcode.com/problems/smallest-subsequence-of-distinct-characters/
Solutions#
Solution 1: Stack#
We use an array last
to record the last occurrence of each character, a stack to save the result string, and an array vis
or an integer variable mask
to record whether the current character is in the stack.
Traverse the string $s$, for each character $c$, if $c$ is not in the stack, we need to check whether the top element of the stack is greater than $c$. If it is greater than $c$ and the top element of the stack will appear later, we pop the top element of the stack and push $c$ into the stack.
Finally, concatenate the elements in the stack into a string and return it as the result.
The time complexity is $O(n)$, and the space complexity is $O(n)$. Where $n$ is the length of the string $s$.
1
2
3
4
5
6
7
8
9
10
11
12
13
| class Solution:
def removeDuplicateLetters(self, s: str) -> str:
last = {c: i for i, c in enumerate(s)}
stk = []
vis = set()
for i, c in enumerate(s):
if c in vis:
continue
while stk and stk[-1] > c and last[stk[-1]] > i:
vis.remove(stk.pop())
stk.append(c)
vis.add(c)
return ''.join(stk)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| class Solution {
public String removeDuplicateLetters(String s) {
int n = s.length();
int[] last = new int[26];
for (int i = 0; i < n; ++i) {
last[s.charAt(i) - 'a'] = i;
}
Deque<Character> stk = new ArrayDeque<>();
int mask = 0;
for (int i = 0; i < n; ++i) {
char c = s.charAt(i);
if (((mask >> (c - 'a')) & 1) == 1) {
continue;
}
while (!stk.isEmpty() && stk.peek() > c && last[stk.peek() - 'a'] > i) {
mask ^= 1 << (stk.pop() - 'a');
}
stk.push(c);
mask |= 1 << (c - 'a');
}
StringBuilder ans = new StringBuilder();
for (char c : stk) {
ans.append(c);
}
return ans.reverse().toString();
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| class Solution {
public:
string removeDuplicateLetters(string s) {
int n = s.size();
int last[26] = {0};
for (int i = 0; i < n; ++i) {
last[s[i] - 'a'] = i;
}
string ans;
int mask = 0;
for (int i = 0; i < n; ++i) {
char c = s[i];
if ((mask >> (c - 'a')) & 1) {
continue;
}
while (!ans.empty() && ans.back() > c && last[ans.back() - 'a'] > i) {
mask ^= 1 << (ans.back() - 'a');
ans.pop_back();
}
ans.push_back(c);
mask |= 1 << (c - 'a');
}
return ans;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| func removeDuplicateLetters(s string) string {
last := make([]int, 26)
for i, c := range s {
last[c-'a'] = i
}
stk := []rune{}
vis := make([]bool, 128)
for i, c := range s {
if vis[c] {
continue
}
for len(stk) > 0 && stk[len(stk)-1] > c && last[stk[len(stk)-1]-'a'] > i {
vis[stk[len(stk)-1]] = false
stk = stk[:len(stk)-1]
}
stk = append(stk, c)
vis[c] = true
}
return string(stk)
}
|
Solution 2#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| class Solution:
def removeDuplicateLetters(self, s: str) -> str:
count, in_stack = [0] * 128, [False] * 128
stack = []
for c in s:
count[ord(c)] += 1
for c in s:
count[ord(c)] -= 1
if in_stack[ord(c)]:
continue
while len(stack) and stack[-1] > c:
peek = stack[-1]
if count[ord(peek)] < 1:
break
in_stack[ord(peek)] = False
stack.pop()
stack.append(c)
in_stack[ord(c)] = True
return ''.join(stack)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| func removeDuplicateLetters(s string) string {
count, in_stack, stack := make([]int, 128), make([]bool, 128), make([]rune, 0)
for _, c := range s {
count[c] += 1
}
for _, c := range s {
count[c] -= 1
if in_stack[c] {
continue
}
for len(stack) > 0 && stack[len(stack)-1] > c && count[stack[len(stack)-1]] > 0 {
peek := stack[len(stack)-1]
stack = stack[0 : len(stack)-1]
in_stack[peek] = false
}
stack = append(stack, c)
in_stack[c] = true
}
return string(stack)
}
|