|
| 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 | + |
0 commit comments