第三题:T3最大的数字
标签:字符串、栈、贪心
题意:给定一个十进制整数
n
n
n ,保证
n
n
n 的首位不为
0
0
0,你必须删除其中
d
d
d 个数字,使得留下的数字最大。请输出留下的最大数。
(
1
≤
n
<
1
0
300000
1≤n<10^{300000}
1≤n<10300000, 1≤ d <n)
题解:要使得最后留下的数最大,想着把前面稍微比较小的数删掉,后面大一点的数字顶上来。
比如
417
417
417,如果要删除一个数,我们会把
1
1
1删除,然后
7
7
7顶上来,形成
47
47
47。
如何实现这样的逻辑呢?我们考虑维护一个栈,由于栈后进先出的性质,我们遍历到每一位的时候可以去检测一下和栈顶元素的大小关系,如果目前还能删数,并且当前元素比栈顶元素(前面的数)大,那我们可以把栈顶元素弹掉,等价于删除栈顶元素。那么最后留下来的就能保证比较大。
可能整个过程中删除数不够,其实已经维护了一个递减序列(非严格),那我们把末尾的一些删掉即可。
比如原数为
86421
86421
86421,
d
=
2
d=2
d=2,那么遍历的过程中不会因为栈顶和当前数的关系删除的情况。
最终我们把最后两个元素删掉,形成
864
864
864就好了。
代码:
#include <bits/stdc++.h>
using namespace std;
int d;
string str, ans = "";
stack<char> s;
int main() {
cin >> d >> str;
int len = str.size();
for (int i = 0; i < len; i++) {
// 当d>0的时候,如果栈顶比当前字符小 弹出
while (d > 0 && !s.empty() && s.top() < str[i]) {
s.pop();
d--;
}
s.push(str[i]);
}
while (!s.empty()) {
if (d > 0) d--;
else ans = s.top() + ans;
s.pop();
}
cout << ans << endl;
return 0;
}