LeetCode 2030. 含特定字母的最小子序列
Posted 英雄哪里出来
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 2030. 含特定字母的最小子序列相关的知识,希望对你有一定的参考价值。
文章目录
一、题目
1、题目描述
给你一个字符串 s s s ,一个整数 k k k ,一个字母
letter
以及另一个整数repetition
。
返回 s s s 中长度为 k k k 且 字典序最小 的子序列,该子序列同时应满足字母letter
出现 至少repetition
次。生成的测试用例满足letter
在 s s s 中出现 至少repetition
次。
样例输入:s = "leetcode", k = 4, letter = "e", repetition = 2
样例输出:"ecde"
2、基础框架
- C++ 版本给出的基础框架代码如下:
class Solution
public:
string smallestSubsequence(string s, int k, char letter, int repetition)
;
3、原题链接
二、解题报告
1、思路分析
(
1
)
(1)
(1) 首先梳理条件:
(
1.1
)
(1.1)
(1.1) 长度为
k
k
k 的子序列;
(
1.2
)
(1.2)
(1.2) 字典序最小;
(
1.3
)
(1.3)
(1.3) 正好有 repetition
个字符letter
;
(
2
)
(2)
(2) 如果没有第三个条件,我们怎么做?
(
3
)
(3)
(3) 可以考虑用一个栈,栈里的元素,从栈底到栈顶单调不降。考虑栈顶元素
x
x
x,当前枚举到的元素
y
y
y,并且栈里的元素 + 还没有枚举的元素的个数,大于等于
k
k
k,有三种情况:
(
3.1
)
(3.1)
(3.1)
x
>
y
x \\gt y
x>y,将
x
x
x 出栈。反复判断,直到栈底到栈顶单调不降。
(
3.2
)
(3.2)
(3.2) 将
y
y
y 入栈;
(
4
)
(4)
(4) 模拟一下leetcode
这个单词:
(
4.1
)
(4.1)
(4.1) l
入栈;
(
4.2
)
(4.2)
(4.2) l > e
,则l
出栈,e
入栈;
(
4.3
)
(4.3)
(4.3) e <= e
,e
入栈;
(
4.4
)
(4.4)
(4.4) e < t
,t
入栈;
(
4.5
)
(4.5)
(4.5) t > c
,则t
出栈,则e
出栈,则e
出栈,则l
出栈,c
入栈;
(
4.6
)
(4.6)
(4.6) 这时候栈里面一个c
,外面只剩下ode
,总共四个字符,所以就是code
为字典序最小的情况;当然,这是没有考虑repetition
的情况时的解。最后,将栈强制出栈得到一个
k
k
k 个长度的栈,逆序就是要求的满足条件
(
1.1
)
(1.1)
(1.1) 和
(
1.2
)
(1.2)
(1.2) 的字符串。
(
7
)
(7)
(7) 那么,如何满足正好有 repetition
个字符letter
字符呢?
(
8
)
(8)
(8) 首先,可以用一个后缀和来记录后面的字符串,还有多少个letter
字符。以及cnt
代表当前栈中有多少个字符,进行出栈之前需要增加一个条件:如果栈中letter
字符 + 后缀还剩余字符等于repetition
,并且当前栈顶元素是letter
字符,则不能出栈。
(
9
)
(9)
(9) 遍历完毕以后,栈中的字符数可能大于
k
k
k 个,于是需要去掉末尾的字符,并且记录多删除的letter
的数目,并且在最后给它补偿回来。
2、时间复杂度
时间复杂度 O ( n ) O(n) O(n) 。
3、代码详解
class Solution
public:
string smallestSubsequence(string s, int k, char letter, int repetition)
int sum[100000], hash[100000];
stack<char> stk;
string ret;
int i;
int n = s.size();
int cnt = 0;
sum[n] = 0;
for(i = n-1; i >= 0; --i)
sum[i] = (s[i] == letter ? 1 : 0) + sum[i+1];
for(i = 0; i < n; ++i)
while(stk.size() + (n - i) > k && stk.size() && stk.top() > s[i])
if(cnt + sum[i] == repetition && stk.top() == letter)
break;
if(stk.top() == letter) --cnt;
stk.pop();
stk.push(s[i]);
if(s[i] == letter) ++cnt;
// 这一趟下来,cnt == repetition,但是长度有可能大于 k
while(stk.size() > k)
cnt -= (stk.top() == letter ? 1 : 0);
stk.pop();
while(stk.size())
ret += stk.top();
stk.pop();
reverse(ret.begin(), ret.end());
int x = k - 1;
while(cnt < repetition)
cnt += (ret[x] != letter);
ret[x] = letter;
--x;
return ret;
;
三、本题小知识
单调栈的问题,可以先考虑两个元素的大小关系,逐渐就能清晰的明白栈是应该用递增栈,还是递减栈。
四、加群须知
相信看我文章的大多数都是「 大学生 」,能上大学的都是「 精英 」,那么我们自然要「 精益求精 」,如果你还是「 大一 」,那么太好了,你拥有大把时间,当然你可以选择「 刷剧 」,然而,「 学好算法 」,三年后的你自然「 不能同日而语 」。
那么这里,我整理了「 几十个基础算法 」 的分类,点击开启:
如果链接被屏蔽,或者有权限问题,可以私聊作者解决。
大致题集一览:
为了让这件事情变得有趣,以及「 照顾初学者 」,目前题目只开放最简单的算法 「 枚举系列 」 (包括:线性枚举、双指针、前缀和、二分枚举、三分枚举),当有 一半成员刷完 「 枚举系列 」 的所有题以后,会开放下个章节,等这套题全部刷完,你还在群里,那么你就会成为「 夜深人静写算法 」专家团 的一员。
不要小看这个专家团,三年之后,你将会是别人 望尘莫及 的存在。如果要加入,可以联系我,考虑到大家都是学生, 没有「 主要经济来源 」,在你成为神的路上,「 不会索取任何 」。
🔥联系作者,或者扫作者主页二维码加群,加入刷题行列吧🔥
🔥让天下没有难学的算法🔥
C语言免费动漫教程,和我一起打卡! 🌞《光天化日学C语言》🌞
让你养成九天持续刷题的习惯 🔥《九日集训》🔥
入门级C语言真题汇总 🧡《C语言入门100例》🧡
组团学习,抱团生长 🌌《算法零基础100讲》🌌
几张动图学会一种数据结构 🌳《画解数据结构》🌳
竞赛选手金典图文教程 💜《夜深人静写算法》💜
以上是关于LeetCode 2030. 含特定字母的最小子序列的主要内容,如果未能解决你的问题,请参考以下文章