PAT 1019 数字黑洞
给定任一个各位数字不完全相同的 4 位正整数,如果我们先把 4 个数字按非递增排序,再按非递减排序,然后用第 1 个数字减第 2 个数字,将得到一个新的数字。一直重复这样做,我们很快会停在有“数字黑洞”之称的 6174,这个神奇的数字也叫 Kaprekar 常数
即输入四位数,升序降序排列,构成最大和最小数相减,不停作差,最后所得一定为6174
首先给出代码
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num[4];
int figure,flag=0;
int i,j,max,min,temp;
scanf("%d",&figure);
while((figure!=6174&&figure!=0)||flag==0)
{
flag=1;
num[0]=figure%10;
num[1]=figure/10%10;
num[2]=figure/100%10;
num[3]=figure/1000%10;
for(i=0;i<3;i++)
{
for(j=0;j<3-i;j++)
{
if(num[j+1]>num[j])
{
temp=num[j];
num[j]=num[j+1];
num[j+1]=temp;
}
}
}
max=1000*num[0]+100*num[1]+10*num[2]+num[3];
min=1000*num[3]+100*num[2]+10*num[1]+num[0];
figure=max-min;
printf("%04d - %04d = %04d\n",max,min,figure);
}
return 0;
}
对于这道题,我的思考
- 如何存4位数,并且升序降序,最后做减法
- 具体用哪种排序方法
- 如何设置循环的终止条件,考虑对于特殊情况的测试
1、关于如何存储四位数,受之前做的题目的影响,我开始想当成字符串形式来存储,主要有我的顾忌:
存到一个int类型的变量里,再依次取余数存到指定数组里,这样操作起来很麻烦
这是因为我受之前做的题目的影响,我开始以为输入的是多位数,后来仔细读题看清是只有四位数
所以还是选择了:先将数字赋值给figure,再依次取余数放入数组中
num[0]=figure%10;
num[1]=figure/10%10;
num[2]=figure/100%10;
num[3]=figure/1000%10;
2、关于排序方法
通过刷题,我发现我对排序算法的掌握还很差,基本很难记住,这是一定一定要加强的
这道题还是采用熟悉的冒泡排序,可是在实际操作中却出现了很多错误,
所以加强对排序算法的熟悉和训练!!!
for(i=0;i<3;i++)
{
for(j=0;j<3-i;j++)
{
if(num[j+1]>num[j])
{
temp=num[j];
num[j]=num[j+1];
num[j+1]=temp;
}
}
}
3、对于循环条件的设置,这应该这道题的重点所在
- 结果不等于6174
- 结果不等于0
- 开始输入6174要可以进入循环
对于前两个要求实现起来不难
figure!=6174&&figure!=0
主要是第三个限制条件
我在这里设置了标志符 flag ,初始化为0
对于特例 figure = 6174 ,我只要保证第一次可以进入循环即可
所以设置循环条件
while((figure!=6174&&figure!=0)||flag==0)
这样第一次进入循环时,由于 flag == 0 成立,又因为或关系,循环条件一定成立
进入循环后,马上将flag赋值为1
这样 或后面的判断条件为假,则只用看前面的限制条件即可
最后一个测试点是输出,开始的时候我只按 %d 格式输出,这样会忽略前面的0,
过不了测试点,更改后
printf("%04d - %04d = %04d\n",max,min,figure);
这里附上 printf 的输出控制方法
特殊的输出方法比如输出的形式为printf(“%4d”,n);
这个4是指输出的空间为4,比如输出80,80占两个格,则前面补两个空格,如果输出位数大于预定位数,则按实际位数输出。
输出的形式为printf(“%.2f”,n);就是保留两位小数的意思,2我是可以换的比如保留3位小数,输出的形式为printf(“%.3f”,n);