持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情
删数问题
题目描述
键盘输入一个高精度的正整数 N(不超过 250 位),去掉其中任意 k 个数字后剩下的数字按原左右次序将组成一个新的非负整数。编程对给定的 N 和 k,寻找一种方案使得剩下的数字组成的新数最小。
输入格式
n(高精度的正整数 )。
k(需要删除的数字个数 )。
输出格式
最后剩下的最小数。
样例 #1
样例输入 #1
175438
4
样例输出 #1
13
题目大意与解题思路:
题意: 删去k个数字,使剩下的数字最小。
思考: 如果第 i 个数比第 i-1个数大,那么我们称第 i个数可以删掉第 i-1个数。这样,我们就可以采用对于一个数暴力往前跳然后删除的算法。
题解:
这是一个贪心思想,高位尽量选小的,但是顺序又不能改变
所以循环时边界条件不是数的长度,而是长度-还剩的要选的个数
- 考虑两个数字,高位低的数字会更小,随后保证低位小。
- 因此采用单调栈维护一个
n-k长的上升序列,如果新入栈的数比栈顶小就一直出栈直到不小为止。
- 因为序列要保证长度,每个数只会入栈一次,出栈就删一个数。不过很有可能没删完就结束了。
- 循环结束,需要把n-k以上的删完。特
- 特判下前导0。
举个例子
首先来看一个例子-> 输入n和4
- n=175438 //删掉7
- 15438 //删掉5
- 1438 //删掉4
- 138 //删掉8
- 13 //解为13
Code
#include<bits/stdc++.h>
using namespace std;
char ans[256];
int main(){
string s;
int k;;
cin>>s>>k;
int n = s.size();
stack<char>st;
st.push(s[0]);
int c=0;
for(int i=1;i<n;i++){
while(!st.empty()&&st.top()>s[i]&&c<k){
st.pop();
c++;
}
st.push(s[i]);
}
while(c<k){
st.pop();
c++;
}
c=n-k;
ans[c--]='\0';
while(c>=0) ans[c--]=st.top(),st.pop();
c = 0;
while(c<n-k-1&&ans[c]=='0') c++;
printf("%s",ans+c);
return 0;
}