题目描述
键盘输入一个高精度的正整数N(不超过250位) ,去掉其中任意k个数字后剩下的数字按原左右次序将组成一个新的正整数。编程对给定的N和k,寻找一种方案使得剩下的数字组成的新数最小。
输入格式
输入两行正整数。
第一行输入一个高精度的正整数n。
第二行输入一个正整数K,表示需要删除的数字个数。
输出格式
输出一个整数,最后剩下的最小数。
输入输出样例
输入 #1
175438 4
输出 #1
13
解题思路(by myself)
当我第一次看到这个题的时候,我便被它深深吸引着,是心动的感觉吗?不,是灵光乍现!
只要将各个位存在数组里,然后把大的数字挑出来删了,这不就解出来了?
于是我立马开始敲,成功地敲出了以下代码
#include<stdio.h>
int C (int n)//此处是一个函数,用来输出各个位的数。
{
n/=10;
return n;
}
int main()
{
int k,n;//定义k,n。
scanf("%d\n",&n);
int A[251];//因为位数有250个,所以开辟一个容量251个的数组(莫名奇妙感觉多一个空间不容易错)。
scanf("%d",&k);
for(int a=0;n!=0;a++)//for循环存数,条件则是n!=0,实际上是模仿的while函数,只是个人喜好,可随意改。
{
A[a]=n%10;//将n的各个位存在A[a]中。
n=C(n);
}
//注意,此代码并不完整,只是用于介绍思路,想要直接copy的请继续看下面的哦。
当我敲到这时,我大脑突然泵机了一下,然后冷却了一下,发现了好几个技术问题:
1.因为我存代码数组是存的n除以10的余数,所以实际上A[0]是个位,A[1]是十位,即若用for循环从0开始输出A[0]的话,是反过来的数。
2.数组的长度不知道,也就是如果想要反过来输出的话,还得知道数组长度(跟问题1属于是铁索连环了).
3.咋个删除数组里咱想删除的数呢?咱想删的又是哪些数呢?
于是经过我冥思苦想,欸,弄一碗代码给你看看!
#include<stdio.h>
int C(int n)此处是一个函数,用来输出各个位的数。
{
n/=10;
return n;
}
int main()
{
int k,d=0;//定义k,n,此处还加了一个d,用于统计长度。
int n;
scanf("%d\n",&n);
int A[251];
scanf("%d",&k);
for(int a=0;n!=0;a++)for循环存数,条件则是n!=0,实际上是模仿的while函数,只是个人喜好,可随意改。
{
A[a]=n%10;
n=C(n);
d++;//此处多加了一个d,for循环几次,即n有多少位,所以d就是长度.
}//其实也可以不用d,可以用strlen函数,只是要加头文件.
for(int a=9;a>0;a--)//第一个for循环为了遍历数组时让数组最大数到小一一去除。而不=0是因为各个位上数字都在0~9之间,而0是最小,可以不考虑0.
{for(int b=d-1;b>=0;b--)//此行代码是为了遍历数组各位,其中d便是长度,而0~d-1则是数组第一位到第d位的数。而让b从d-1开始则刚好解决了刚才的问题1.
{if(A[b]==a){
A[b]=-1;//既然数组数字都在0~9,所以让它为负就相当于把它删了( •̀ ω •́ )y
k--;}//k为要删几个数,所以删一个就减一个。
if(k==0){break;}
}if(k==0){break;}
}
for(int a=d-1;a>=0;a--)//遍历数组.
{if(A[a]>=0){
printf("%d",A[a]);}}//输出各位
return 0;}
好嘞,这不就搞定了!
(思路归根结底其实就是删除原整数的最大元素,然后用剩下拼凑出的整数自然是最小的整数喽)运行试试
嘿,对了!.............吗?
不对,这个高精度整数是什么鬼?
等等,250位整数,是不是有点过于大了啊?
输个大点的数试试?
输入例(此为个人自己想的例)
7654321123456
5
戳啦!怎么办!(注意此处如果直接提交大概是部分正确,但因为我在交之前检查了下且为了保AC率所以没有亲身试试)
不如我们换种思路?
用字符串如何?
看代码!
#include<stdio.h>
#include <string.h>//因为这里用strlen算字符串长所以要加头文件
int main()
{char A[251]={0};//设字符串组
int k,d;
scanf("%s\n",&A);//输入字符串.
scanf("%d",&k);//要删多少位.
d=strlen(A);//d为字符串长度.
for(int a='9';a>'0';a--)//注意,此处是字符'9'与字符'0',因为存进去的现在是字符串.
{for(int b=d;b>=0;b--)//还是遍历数组。
{if(A[b]==a){
A[b]=-1;//还是一样的删数方式.
k--;}
if(k==0){break;}//注意k==0了就break,别删多了.
}if(k==0){break;}
}
for(int a=0;a<d;a++)
{if(A[a]>='0'){
printf("%c",A[a]);}}//输出0以上的数,不就是相当于删了要删的数喽?
return 0;}
那么运行试试!
对啦!(顺带一提后来提交到我们的oj上也对了(๑•̀ㅂ•́)و✧)
顺便一提此方法也有一些小瑕疵 ,比如若删了最大数后一位是0该怎么办?如果你提交我最终代码显示部分正确的话,那就是它有个事例是删了数字后首位是0.(不过究竟该省了少一位还是该加上去0这个可能要看题目本身设置了).
还有就是这种方式是输出的字符串,而题目要求是输出整数...有些微妙耶(lll¬ω¬).
不过这是我第一次发博客,可能代码确实有些问题我自己也没有找到(BUG嘛,常有的事。)
但这次博客如果能帮助你或者展示一种新的思路的话,这篇博客也有了它自己的价值。
所以,一起加油学习敲代码吧(ง๑•̀ㅂ•́)ง!