LeetCode 2030. 含特定字母的最小子序列

给你一个字符串 s ,一个整数 k ,一个字母 letter 以及另一个整数 repetition 。

返回 s 中长度为 k 且 字典序最小 的子序列,该子序列同时应满足字母 letter 出现 至少 repetition 次。生成的测试用例满足 letter 在 s 中出现 至少 repetition 次。

子序列 是由原字符串删除一些(或不删除)字符且不改变剩余字符顺序得到的剩余字符串。

字符串 a 字典序比字符串 b 小的定义为:在 a 和 b 出现不同字符的第一个位置上,字符串 a 的字符在字母表中的顺序早于字符串 b 的字符。

示例 1:

输入:s = "leet", k = 3, letter = "e", repetition = 1
输出:"eet"
解释:存在 4 个长度为 3 ,且满足字母 'e' 出现至少 1 次的子序列:
- "lee"("leet")
- "let"("leet")
- "let"("leet")
- "eet"("leet")
其中字典序最小的子序列是 "eet" 。
示例 2:

输入:s = "leetcode", k = 4, letter = "e", repetition = 2
输出:"ecde"
解释:"ecde" 是长度为 4 且满足字母 "e" 出现至少 2 次的字典序最小的子序列。
示例 3:

输入:s = "bb", k = 2, letter = "b", repetition = 2
输出:"bb"
解释:"bb" 是唯一一个长度为 2 且满足字母 "b" 出现至少 2 次的子序列。
 

提示:

1 <= repetition <= k <= s.length <= 5 * 104
s 由小写英文字母组成
letter 是一个小写英文字母,在 s 中至少出现 repetition 次

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/smallest-k-length-subsequence-with-occurrences-of-a-letter
 

解法:

贪心+单调栈。本题要是没有字母 letter 以及另一个整数 repetition的限制就是与 402. 移掉 K 位数字 一样。本题就是要移除n-k个字母,但又有letter的限制,需要在一开始计算letter的总个数,当经过单调栈后,栈中保存的letter个数至少是repetition个。仿造402中截断大于限制的个数,缺少几个在后面更改非letter的字母为letter。

class Solution {
public:
	string smallestSubsequence(string s, int k, char letter, int repetition) {
		deque<char> dq;
		int total = 0;
		for (auto ss : s)
		{
			if (ss == letter)
				++total;
		}
		
		int len = s.length();
		int toErase = len - k;
		int cnt = 0; //队列中有多少letter
		for (int i = 0; i < len; i++)
		{
			while (!dq.empty() && toErase>0&&s[i] < dq.back())
			{
				if (dq.back() == letter)
				{
					if (cnt - 1 + total >= repetition)
						--cnt;
					else break;
				}
				dq.pop_back();
				--toErase;
			}
			dq.push_back(s[i]);
			if (s[i] == letter)
			{
				cnt++;
				total--;
			}
		}
		string ans = "";
		for (auto d : dq)
		{
			ans += d;
		}
		int lena = ans.length();
		while (toErase)
		{
			if (ans.back() == letter)
				cnt--;
			--toErase;
			ans.pop_back();
		}
		for (int i = k - 1; i >= 0; i--)
		{
			if (cnt<repetition&& ans[i] != letter)
			{
				ans[i] = letter;
				cnt++;
			}
		}
		return ans;
	}
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值