删数问题(萌新小码农的C语言解题思路)

题目描述

键盘输入一个高精度的正整数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嘛,常有的事。)

但这次博客如果能帮助你或者展示一种新的思路的话,这篇博客也有了它自己的价值。

所以,一起加油学习敲代码吧(ง๑•̀ㅂ•́)ง!

  • 10
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值