Skip to content

Commit 75dee55

Browse files
author
robot
committed
feat: $2030
1 parent 7a053c4 commit 75dee55

File tree

3 files changed

+133
-0
lines changed

3 files changed

+133
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
516516
- [1883. 准时抵达会议现场的最小跳过休息次数](./problems/5775.minimum-skips-to-arrive-at-meeting-on-time.md)
517517
- [1970. 你能穿过矩阵的最后一天](./problems/1970.last-day-where-you-can-still-cross.md)
518518
- [2009. 使数组连续的最少操作数](./problems/2009.minimum-number-of-operations-to-make-array-continuous.md)
519+
- [2030. 含特定字母的最小子序列](./problems/2030.smallest-k-length-subsequence-with-occurrences-of-a-letter.md)
519520

520521
## :trident:  anki 卡片
521522

SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,5 +338,6 @@
338338
- [1883. 准时抵达会议现场的最小跳过休息次数](./problems/5775.minimum-skips-to-arrive-at-meeting-on-time.md)
339339
- [1970. 你能穿过矩阵的最后一天](./problems/1970.last-day-where-you-can-still-cross.md)
340340
- [2009. 使数组连续的最少操作数](./problems/2009.minimum-number-of-operations-to-make-array-continuous.md)
341+
- [2030. 含特定字母的最小子序列](./problems/2030.smallest-k-length-subsequence-with-occurrences-of-a-letter.md)
341342

342343
- [后序](epilogue.md)
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
## 题目地址(2030. 含特定字母的最小子序列)
2+
3+
https://leetcode-cn.com/problems/smallest-k-length-subsequence-with-occurrences-of-a-letter/
4+
5+
## 题目描述
6+
7+
```
8+
给你一个字符串 s ,一个整数 k ,一个字母 letter 以及另一个整数 repetition 。
9+
10+
返回 s 中长度为 k 且 字典序最小 的子序列,该子序列同时应满足字母 letter 出现 至少 repetition 次。生成的测试用例满足 letter 在 s 中出现 至少 repetition 次。
11+
12+
子序列 是由原字符串删除一些(或不删除)字符且不改变剩余字符顺序得到的剩余字符串。
13+
14+
字符串 a 字典序比字符串 b 小的定义为:在 a 和 b 出现不同字符的第一个位置上,字符串 a 的字符在字母表中的顺序早于字符串 b 的字符。
15+
16+
 
17+
18+
示例 1:
19+
20+
输入:s = "leet", k = 3, letter = "e", repetition = 1
21+
输出:"eet"
22+
解释:存在 4 个长度为 3 ,且满足字母 'e' 出现至少 1 次的子序列:
23+
- "lee"("leet")
24+
- "let"("leet")
25+
- "let"("leet")
26+
- "eet"("leet")
27+
其中字典序最小的子序列是 "eet" 。
28+
29+
30+
示例 2:
31+
32+
输入:s = "leetcode", k = 4, letter = "e", repetition = 2
33+
输出:"ecde"
34+
解释:"ecde" 是长度为 4 且满足字母 "e" 出现至少 2 次的字典序最小的子序列。
35+
36+
37+
示例 3:
38+
39+
输入:s = "bb", k = 2, letter = "b", repetition = 2
40+
输出:"bb"
41+
解释:"bb" 是唯一一个长度为 2 且满足字母 "b" 出现至少 2 次的子序列。
42+
43+
44+
 
45+
46+
提示:
47+
48+
1 <= repetition <= k <= s.length <= 5 * 104
49+
s 由小写英文字母组成
50+
letter 是一个小写英文字母,在 s 中至少出现 repetition 次
51+
```
52+
53+
## 前置知识
54+
55+
- 单调栈
56+
57+
## 公司
58+
59+
- 暂无
60+
61+
## 思路
62+
63+
之前我写了一篇文章,里面详细介绍了单调栈解决这种删除若干并求最小(或最大)字典序的题目,没有看过的建议先看下那篇文章 [一招吃遍力扣四道题,妈妈再也不用担心我被套路啦~](https://lucifer.ren/blog/2021/02/20/%E5%88%A0%E9%99%A4%E9%97%AE%E9%A2%98/)
64+
65+
这道题实际上就是上文提到的 402 号题目的进阶。也就是我们需要多考虑 **repetition 个 letter** 的情况。
66+
67+
和 402 类似,只不过我们需要多加几个判断:
68+
69+
1. 在 stack 栈顶是 letter 的情况不能随意 pop,这是因为 pop `可能` 导致永远无法满足 **repetition 个 letter**
70+
2. 最后不能直接取 stack 前 remain 个。因为可能导致永远无法满足 **repetition 个 letter**,因此需要记录一下剔除超过 remain 部分元素后,我们剔除了多少 letter(假设为 m 个),之后把末尾的 m 个非 letter 替换为 letter 以满足 repetiton 的要求
71+
72+
经过上面的操作,我们能保证 stack 是满足 **repetition 个 letter** 情况下的最小的字典序。
73+
74+
## 关键点
75+
76+
- 先不考虑 repetition,这就是一个典型的单调栈题目
77+
78+
## 代码
79+
80+
- 语言支持:Python3
81+
82+
Python3 Code:
83+
84+
```python
85+
86+
class Solution:
87+
def smallestSubsequence(self, s: str, k: int, letter: str, repetition: int) -> str:
88+
stack = []
89+
remain, k = k, len(s) - k
90+
pre_letters, pos_letters = 0, s.count(letter)
91+
for a in s:
92+
while k and stack and stack[-1] > a:
93+
if stack[-1] == letter:
94+
if repetition > pre_letters + pos_letters - 1: break # 重要
95+
pre_letters -= 1
96+
stack.pop()
97+
k -= 1
98+
if a == letter:
99+
pre_letters += 1
100+
pos_letters -= 1
101+
stack.append(a)
102+
# 不能直接取前 remain 个,因为可能不满足 repetition 的要求,因此需要记录一下剔除超过 remain 部分元素后,我们剔除了多少 letter(假设为 m 个),之后把末尾的 m 个非 letter 替换为 letter 以满足 repetiton 的要求
103+
while len(stack) > remain:
104+
if stack[-1] == letter:
105+
pre_letters -= 1
106+
stack.pop()
107+
for i in range(remain-1,-1,-1):
108+
if pre_letters < repetition and stack[i] != letter:
109+
pre_letters += 1
110+
stack[i] = letter
111+
return ''.join(stack)
112+
113+
114+
```
115+
116+
**复杂度分析**
117+
118+
令 n 为数组长度。
119+
120+
- 时间复杂度:$O(n)$
121+
- 空间复杂度:$O(n)$
122+
123+
> 此题解由 [力扣刷题插件](https://leetcode-pp.github.io/leetcode-cheat/?tab=solution-template) 自动生成。
124+
125+
力扣的小伙伴可以[关注我](https://leetcode-cn.com/u/fe-lucifer/),这样就会第一时间收到我的动态啦~
126+
127+
以上就是本文的全部内容了。大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 45K star 啦。大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。
128+
129+
关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。
130+
131+
![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfcuzagjalj30p00dwabs.jpg)

0 commit comments

Comments
 (0)