Skip to content

Commit 2621e52

Browse files
committed
Create 1081. 不同字符的最小子序列.md
1 parent a61b2a9 commit 2621e52

1 file changed

Lines changed: 55 additions & 0 deletions

File tree

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
## [1081. 不同字符的最小子序列](https://leetcode-cn.com/problems/smallest-subsequence-of-distinct-characters/)
2+
3+
- 标签:栈、贪心、字符串、单调栈
4+
- 难度:中等
5+
6+
## 题目大意
7+
8+
给定一个字符串 `s`
9+
10+
要求:返回 `s` 字典序最小的子序列,该子序列包含 `s` 的所有不同字符,且只包含一次。
11+
12+
## 解题思路
13+
14+
针对题目的两个要求:包含所有不同字符,且只包含一次(去重)、子序列(不能打乱其他字符顺序)、字典序最小。我们来一一进行分析。
15+
16+
1. 包含所有不同字符,且只包含一次(去重):可以通过 **「使用哈希表存储字母出现次数」** 的方式,将每个字母出现的次数统计起来,再遍历一遍,去除重复的字母。
17+
2. 子序列(不能打乱其他字符顺序):按顺序遍历,将非重复的字母存储到答案数组或者栈中,最后再拼接起来,就能保证不打乱其他字符顺序。
18+
3. 字典序最小:意味着字典序小的字母应该尽可能放在前面。
19+
- 对于第 `i` 个字符 `s[i]` 而言,如果第 `0` ~ `i - 1` 之间的某个字符 `s[j]``s[i]` 之后不再出现了,那么 `s[j]` 必须放到 `s[i]` 之前。
20+
- 而如果 `s[j]` 在之后还会出现,并且 `s[j]` 的字典序大于 `s[i]`,我们则可以先舍弃 `s[j]`,把 `s[i]` 尽可能的放到前面。后边再考虑使用 `s[j]` 所对应的字符。
21+
22+
要满足第 3 条需求,我们可以使用 **「单调栈」** 来解决。我们使用单调栈存储 `s[i]` 之前出现的非重复、并且字典序最小的字符序列。整个算法步骤如下:
23+
24+
- 先遍历一遍字符串,用哈希表 `letter_counts` 统计出每个字母出现的次数。
25+
- 然后使用单调递减栈保存当前字符之前出现的非重复、并且字典序最小的字符序列。
26+
27+
- 当遍历到 `s[i]` 时,如果 `s[i]` 没有在栈中出现过:
28+
- 则比较 `s[i]` 和栈顶元素 `stack[-1]` 的字典序。如果 `s[i]` 的字典序小于栈顶元素 `stack[-1]`,并且栈顶元素之后的出现次数大于 `0`,则将栈顶元素弹出。
29+
- 然后继续判断 `s[i]` 和栈顶元素 `stack[-1]`,并且知道栈顶元素出现次数为 `0` 时停止弹出。此时将 `s[i]` 添加到单调栈中。
30+
- 从哈希表 `letter_counts` 中减去 `s[i]` 出现的次数,继续遍历。
31+
- 最后将单调栈中的字符依次拼接为答案字符串,并返回。
32+
33+
## 代码
34+
35+
```Python
36+
class Solution:
37+
def smallestSubsequence(self, s: str) -> str:
38+
stack = []
39+
letter_counts = dict()
40+
for ch in s:
41+
if ch in letter_counts:
42+
letter_counts[ch] += 1
43+
else:
44+
letter_counts[ch] = 1
45+
46+
for ch in s:
47+
if ch not in stack:
48+
while stack and ch < stack[-1] and stack[-1] in letter_counts and letter_counts[stack[-1]] > 0:
49+
stack.pop()
50+
stack.append(ch)
51+
letter_counts[ch] -= 1
52+
53+
return ''.join(stack)
54+
```
55+

0 commit comments

Comments
 (0)