#T1231. 最小新整数

题目描述

给定一个十进制正整数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. 1.

    ​问题转换​​:

    • 保留m-k位数字

    • 从高位到低位选择尽可能小的数字

  2. 2.

    ​关键策略​​:

    • 使用栈结构维护当前最优序列

    • 从左向右扫描数字,对于每个数字:

      • 当栈不为空、还能删除数字(k>0)且当前数字小于栈顶元素时,弹出栈顶元素(相当于删除),k减1

      • 将当前数字压入栈中

  3. 3.

    ​特殊情况处理​​:

    • 扫描完成后如果k>0,从栈尾删除k个数字(剩余数字是递增的)

  4. 4.

    ​结果构造​​:

    • 栈底到栈顶的数字即为最优结果

    • 不需要处理前导零(题目保证各位数字非0)

示例推演:n=9128456, k=2
  1. 1.

    初始栈:[]

    • '9'入栈 → [9]

  2. 2.

    '1'处理:

    • 1<9 → 弹出9,k-1=1 → [1]

  3. 3.

    '2'处理 → [1,2]

  4. 4.

    '8'处理 → [1,2,8]

  5. 5.

    '4'处理:

    • 4<8 → 弹出8,k-1=0 → [1,2,4]

  6. 6.

    '5','6'入栈 → [1,2,4,5,6]

  7. 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;
}

此代码仅供参考,请勿纯抄

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值