题目描述
给定一个十进制正整数n(0<n<1000000000),每个数位上数字均不为0。n的位数为m。
现在从m位中删除k位(0<k<m),求生成的新整数最小为多少?
例如: n=9128456,k=2,则生成的新整数最小为12456。
输入
第一行t, 表示有t组数据;
接下来t行,每一行表示一组测试数据,每组测试数据包含两个数字n,k。
输出
t行,每行一个数字,表示从n中删除k位后得到的最小整数。
样例
输入数据 1
2
9128456 2
1444 3
输出数据 1
12456
1
来源
一本通在线评测
思路分析:删位求最小整数(贪心策略)
题目要求:给定一个正整数n(各位数字不为0),从m位数中删除k位,使得剩余数字组成的新整数最小。
核心思想:贪心算法
- 1.
问题转换:
- •
保留m-k位数字
- •
从高位到低位选择尽可能小的数字
- •
- 2.
关键策略:
- •
使用栈结构维护当前最优序列
- •
从左向右扫描数字,对于每个数字:
- •
当栈不为空、还能删除数字(k>0)且当前数字小于栈顶元素时,弹出栈顶元素(相当于删除),k减1
- •
将当前数字压入栈中
- •
- •
- 3.
特殊情况处理:
- •
扫描完成后如果k>0,从栈尾删除k个数字(剩余数字是递增的)
- •
- 4.
结果构造:
- •
栈底到栈顶的数字即为最优结果
- •
不需要处理前导零(题目保证各位数字非0)
- •
示例推演:n=9128456, k=2
- 1.
初始栈:[]
- •
'9'入栈 → [9]
- •
- 2.
'1'处理:
- •
1<9 → 弹出9,k-1=1 → [1]
- •
- 3.
'2'处理 → [1,2]
- 4.
'8'处理 → [1,2,8]
- 5.
'4'处理:
- •
4<8 → 弹出8,k-1=0 → [1,2,4]
- •
- 6.
'5','6'入栈 → [1,2,4,5,6]
- 7.
最终结果:12456
时间复杂度
- •
O(m):线性扫描数字(m为n的位数)
- •
高效处理大数据(题目限制n<1e9)
边界情况
- •
当k=m时,删除所有数字(题目保证0<k<m)
- •
数字单调递增时,直接删除后k位(如12345, k=2 → 123)
代码样例
#include<bits/stdc++.h>
using namespace std;
int t;
string n;
int k;
string solve(string s,int d)
{
vector<char>v;
for(int i=0; i<s.size(); i++)
{
char c=s[i];
while(!v.empty() && d>0 && c<v.back())
{
v.pop_back();
d--;
}
v.push_back(c);
}
while(d>0)
{
v.pop_back();
d--;
}
return string(v.begin(),v.end());
}
int main()
{
cin>>t;
while(t--)
{
cin>>n>>k;
cout<<solve(n,k)<<endl;
}
return 0;
}
此代码仅供参考,请勿纯抄
541

被折叠的 条评论
为什么被折叠?



