You are given a string s, an integer k, a letter letter, and an integer repetition.
Return the lexicographically smallest subsequence of s of length k that has the letter letter appear at least repetition times. The test cases are generated so that the letter appears in s at least repetition times.
A subsequence is a string that can be derived from another string by deleting some or no characters without changing the order of the remaining characters.
A string a is lexicographically smaller than a string b if in the first position where a and b differ, string a has a letter that appears earlier in the alphabet than the corresponding letter in b.
Example 1:
Input: s = “leet”, k = 3, letter = “e”, repetition = 1
Output: “eet”
Explanation: There are four subsequences of length 3 that have the letter ‘e’ appear at least 1 time:
- “lee” (from “leet”)
- “let” (from “leet”)
- “let” (from “leet”)
- “eet” (from “leet”)
The lexicographically smallest subsequence among them is “eet”.
Example 2:
example-2
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pNw8a0i6-1679306339945)(null)]
Input: s = “leetcode”, k = 4, letter = “e”, repetition = 2
Output: “ecde”
Explanation: “ecde” is the lexicographically smallest subsequence of length 4 that has the letter “e” appear at least 2 times.
Example 3:
Input: s = “bb”, k = 2, letter = “b”, repetition = 2
Output: “bb”
Explanation: “bb” is the only subsequence of length 2 that has the letter “b” appear at least 2 times.
Constraints:
- 1 <= repetition <= k <= s.length <= 5 * 104
- s consists of lowercase English letters.
- letter is a lowercase English letter, and appears in s at least repetition times.
用一个 monostack 保存当前被选中的字符, 遍历 s, 如果当前字符 s[i] < monostack[-1], 则持续把 monostack[-1]弹出, 直到 monostack[-1] <= s[i]或者后面剩余的字符与 monostack 中的字符不足以组合出符合要求的答案时为止
要想组合出符合要求的答案, 有两个条件:
- 剩余字符数量 + monostack.len() > k
- 剩余的指定字符 letter 的数量 + monostack 中 letter 的数量 > repetition
这样得出的最终 monostack 的长度可能大于 k, 所以我们要反向遍历 monostack 去除掉多余的字符。
impl Solution {
pub fn smallest_subsequence(s: String, k: i32, letter: char, mut repetition: i32) -> String {
let mut remain_letters = s.chars().filter(|&c| c == letter).count();
let mut stack = Vec::new();
for (i, c) in s.chars().enumerate() {
while let Some(last) = stack.pop() {
if last > c && stack.len() + s.len() - i >= k as usize {
if last == letter {
if remain_letters == repetition as usize {
stack.push(last);
break;
}
repetition += 1;
}
continue;
}
stack.push(last);
break;
}
if stack.len() < k as usize || repetition > 0 {
stack.push(c);
if c == letter {
repetition -= 1;
}
}
if c == letter {
remain_letters -= 1;
}
}
let mut need_removed = stack.len() - k as usize;
let mut ans = Vec::new();
for c in stack.into_iter().rev() {
if c != letter && need_removed > 0 {
need_removed -= 1;
continue;
}
ans.push(c);
}
ans.into_iter().rev().collect()
}
}