C语言PAT刷题 - 1023 组个最小数

作者的话:若有朋友复制代码去PAT试着运行遇到问题的:
1.可能是格式问题,可以先把从本站复制的代码粘贴到记事本,再把记事本里的代码复制,然后粘贴到PAT的代码区,提交本题回答,应该就可以了;
2.可能是注释原因,PAT有时候检测到注释会编译错误,所以可以先把注释删了,再进行提交回答;
3.可能是作者当初根据题目写出来的代码仍存在一些疏漏,而恰好当时的测试机制没那么完善,没检测出问题。后面测试机制有所更新,故出现问题,若有相关需要的可以评论区留言或私信作者,我看到的话会去再查一下疏漏之处,然后更新文章。

一、题目描述
给定数字 0-9 各若干个。你可以以任意顺序排列这些数字,但必须全部使用。目标是使得最后得到的数尽可能小(注意 0 不能做首位)。例如:给定两个 0,两个 1,三个 5,一个 8,我们得到的最小的数就是 10015558。
现给定数字,请编写程序输出能够组成的最小的数。
输入格式:
输入在一行中给出 10 个非负整数,顺序表示我们拥有数字 0、数字 1、……数字 9 的个数。整数间用一个空格分隔。10 个数字的总个数不超过 50,且至少拥有 1 个非 0 的数字。
输出格式:
在一行中输出能够组成的最小的数。
输入样例:
2 2 0 0 0 3 0 0 1 0
输出样例:
10015558

二、解题思路
读题:

//1.接收10个非负整数,分别代表0-9十个数字的个数;
//2.输出用这些数字组成的最小的数(0不做首位);
//3.这些数字最多有50个,最大为50个9组合。约等于1050,数字比较大,不用整型存储,采用字符型变量来存储更方便;
//4.因为需要我们输出所有数字组成的最小数,所以其实就是找到最小的非0值,充当最高位,然后紧跟所有的0,最后从小到大跟上各个数字,这样的数字序列组成的数字就是最小的。
思路:
1.定义整型数组a[10]来接收10个非负整数,a[0]=1代表有1个0,a[1]=5代表有5个1,以此类推;定义字符数组c[51]来储存最多50个数字组成的待输出值,多设置一个字符元素是用来存放’\0’,后面输出时可以直接用字符串格式输出这个数字序列;定义其它需要的变量并接收10个非负整数;
2.设置循环,循环从0-9,每一轮循环处理一个数字,循环体将所有的当前数字放到合适的位置,然后开始下一轮循环;
3.调用格式化输出函数printf,把数组c以字符串格式进行输出。

三、具体实现
0.标准C源程序框架

#include <stdio.h>
int main()
{
    return 0;
}

1.定义整型数组a[10]来接收10个非负整数,a[0]=1代表有1个0,a[1]=5代表有5个1,以此类推;定义字符数组c[51]来储存最多50个数字组成的待输出值,多设置一个字符元素是用来存放’\0’,后面输出时可以直接用字符串格式输出这个数字序列;定义其它需要的变量并接收10个非负整数;

    int a[10] = { 0 };
    char c[51]={'\0'};
    int i = 0, j = 1;
    for (i=0;i<10;i++)
    {
        scanf("%d",&a[i]);
    }

2.设置循环,循环从0-9,每一轮循环处理一个数字,循环体将所有的当前数字放到合适的位置,然后开始下一轮循环;

    for (i = 0; i < 10; i++)
    {
        if(i==0)//如果i为0,并且0的个数a[0]>0,把这些0放到紧跟着最高位的后面几位上
            while(a[i] > 0)
            {
                c[j++] = '0';
                a[i]--;//放好一个0,0的数目就减1
            }
        else if ((c[0]=='\0') && a[i])//如果最高位c[0]没有放数字的话,当前i非0且数目>0,把它放到最高位
        {
            c[0] = i + ('0' - 0);//把整数i转化成字符'i'
            a[i]--;
            while (a[i] > 0)//剩下的几个整数i也要放到紧跟0的后面几位上
            {
                c[j++] = i + ('0' - 0);
                a[i]--;
            }
        }
        else
        {
            while (a[i] > 0)
            {
                c[j++] = i + ('0' - 0);
                a[i]--;
            }
        }
    }

3.调用格式化输出函数printf,把数组c以字符串格式进行输出。

    printf("%s",c);

四、测试数据
程序较简单,没什么值得注意的测试数据。
自己写程序时多注意:
1.如何将第一位非0数放到最高位;
2.如果第一个非0数放到最高位了,而它还有多个相同值(如第一个非0数是1,而1有3个,第一个1放好了,后面两个1咋办),如何将那些值放到合适的位置以及那些值会不会被判断语句和循环语句忽略,从而忘记放置那些数字;
3.如果用字符数组放数字,要注意数字0和字符’0’是不一样的,注意类型转换。

五、全部代码

#include <stdio.h>  
int main() {
    int a[10] = { 0 };
    char c[51]={'\0'};
    int i = 0, j = 1;
    for (i=0;i<10;i++)
    {
        scanf("%d",&a[i]);
    }
    for (i = 0; i < 10; i++)
    {
        if(i==0)//如果i为0,并且0的个数a[0]>0,把这些0放到紧跟着最高位的后面几位上
            while(a[i] > 0)
            {
                c[j++] = '0';
                a[i]--;//放好一个0,0的数目就减1
            }
        else if ((c[0]=='\0') && a[i])//如果最高位c[0]没有放数字的话,当前i非0且数目>0,把它放到最高位
        {
            c[0] = i + ('0' - 0);//把整数i转化成字符'i'
            a[i]--;
            while (a[i] > 0)//剩下的几个整数i也要放到紧跟0的后面几位上
            {
                c[j++] = i + ('0' - 0);
                a[i]--;
            }
        }
        else
        {
            while (a[i] > 0)
            {
                c[j++] = i + ('0' - 0);
                a[i]--;
            }
        }
    }
    printf("%s",c);
    return 0;
}

六、优化代码
写完代码后发现前面外层循环中我是先设置判断语句,再在每个分支那里嵌套内层循环,出现了许多赘余。事实上程序进行检测时也应该先判断当前i有没有数目,数目为0的话不管i是几都没关系,数目不为0则不管是几都应该进入循环把当前的多个i放在合适的位置。所以外层循环的循环体中应该再设置一重循环,再在循环内部设置判断语句,根据i的值以及数组c的存放情况存放各个数字;同时a[i]–;这个语句也可以放在循环的条件表达式中,改完之后代码赘余会少很多,不过运行速度应该是没有增加多少的。

#include <stdio.h>  
int main() {
    int a[10] = { 0 };
    char c[51]={'\0'};
    int i = 0, j = 1;
    for (i=0;i<10;i++)
    {
        scanf("%d",&a[i]);
    }
    for (i = 0; i < 10; i++)
    {
        while (a[i]--)
        {
            if (i == 0)
            {
                c[j++] = '0';
            }
            else if (c[0] == '\0')
            {
                c[0] = i + ('0' - 0);
            }
            else
            {
                c[j++] = i + ('0' - 0);
            }
        }
    }
    printf("%s",c);
    return 0;
}
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值