LeetCode每日一题(2030. Smallest K-Length Subsequence With Occurrences of a Letter)

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 中的字符不足以组合出符合要求的答案时为止

要想组合出符合要求的答案, 有两个条件:

  1. 剩余字符数量 + monostack.len() > k
  2. 剩余的指定字符 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()
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值