Skip to content

Commit 960a9a3

Browse files
committed
Added question 316.
1 parent 70ae88c commit 960a9a3

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# 316. Remove Duplicate Letters
2+
3+
## Stack Solution
4+
- Run-time: O(N)
5+
- Space: O(1) or 26
6+
- N = Number of characters in S
7+
8+
To gather the intuition for this solution lets look at a few examples.
9+
10+
```
11+
Example 1:
12+
abc -> abc
13+
14+
Example 2:
15+
cba -> cba
16+
17+
Example 3:
18+
aba -> ab
19+
20+
Example 4:
21+
bab -> ab
22+
23+
Example 5:
24+
xyzabczyx -> abczyx
25+
```
26+
27+
Examples 1 and 2 don't really tell us much but combining them with examples 3 and 4 can.
28+
Notice that example 3 doesn't care about the last letter 'a', while example 4 doesn't care about the first letter 'b'.
29+
30+
Instead of thinking about figuring out which letter to delete, we can think of this by building the word from scratch, from left to right.
31+
With this frame of reference we can reword the question into finding the biggest lexicographic sorted word that doesn't contain duplicates.
32+
33+
From examples 3 and 4, we can then denote that if a letter isn't the last occurring letter, we can build a much larger word that is closer to being lexicographic.
34+
So by using a monotonic stack, that is increasing by nature, we can achieve examples 1 and 3.
35+
A set should be obvious to avoid adding duplicate values into the stack.
36+
However, to achieve examples 2 an 5 with the monotonic stack, we have to add another invariant were we want all last occurring letters.
37+
38+
In summary, we can build the word from left to right using an increasing monotonic stack.
39+
When it comes to popping off the stack, we will continue to pop from the stack if the new letter is smaller than whats on top of the stack AND if whats on top of the stack isn't the last occurring letter.
40+
41+
```
42+
class Solution:
43+
def removeDuplicateLetters(self, s: str) -> str:
44+
stack = list()
45+
seen = set()
46+
ch_to_last_idx = {ch: idx for idx, ch in enumerate(s)}
47+
result = ''
48+
for idx, ch in enumerate(s):
49+
if ch not in seen:
50+
while stack and ch < stack[-1] and idx < ch_to_last_idx[stack[-1]]:
51+
seen.discard(stack.pop())
52+
seen.add(ch)
53+
stack.append(ch)
54+
return ''.join(stack)
55+
```

0 commit comments

Comments
 (0)