做PTA题目前为止感觉最难的一个,开始甚至整体正确思路都没有,只能先尝试从它给的例子入手,先实现题目给的例子,然后列出不足的点,逐渐找思路,进而修改代码,以下内容加程序共花费一下午,博客为实时撰写,从毫无思路到实现程序,还是挺有成就感的。
整个实现过程我分为了两个阶段,第一个阶段是我实现题目给的例子以及特殊情况,程序包括代码1和代码2。第二个阶段是从例子推广到普适性的程序,最终符合题目要求,程序包括代码3和代码4,其中代码4为最终正确代码。
目录
综述:
题目:
输入格式:
输出格式:
输入样例:
输出样例:
第一阶段:
代码1:
代码2:
第二阶段:
代码3:
代码4:
总结:
给定一批整数,分析每个整数的每一位数字,求出现次数最多的个位数字。例如给定3个整数1234、2345、3456,其中出现最多次数的数字是3和4,均出现了3次。
输入在第1行中给出正整数N(≤1000),在第二行中给出N个不超过整型范围的非负整数,数字间以空格分隔。
在一行中按格式“M: n1 n2 ...”输出,其中M是最大次数,n1、n2、……为出现次数最多的个位数字,按从小到大的顺序排列。数字间以空格分隔,但末尾不得有多余空格。
3
1234 2345 3456
3: 3 4
我对这个题感觉是无从下手,我以它输入的例子为参考,首先想到的是把输入的三个数字存到一个数组中,然后遍历这个数组把这里面输入的三个数字的每一位通过while()循环一个个的剥离下来存放在另一个数组,然后对这个存放每一位的数组里面的元素进行遍历比较,得到出现最多的次数,以及出现的元素,
#include
int count = 0;
void div(int num[1000], int size, int x)
{
while (x != 0)
{
num[count] = x % 10;
x /= 10;
count++;
}
}
int main()
{
int n = 0;
scanf("%d", &n);
int arr[1000] = { 0 };
int num[1000] = { 0 };
int i = 0;
int m = 0;
for (i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
for (i = 0; i < n; i++)
{
div(num, sizeof(num) / sizeof(num[0]), arr[i]);
}
int tmp = count;
int rep1 = 0;
int rep = -1;
int tmp1[1000] = { 0 };
for (i = 0; i < tmp; i++)
{
int j = 0;
for (j = 0; j < tmp; j++)
{
if (num[i] == num[j])
{
rep++;
}
}
if (rep1 < rep)
{
rep1 = rep;
tmp1[0] = i;
}
else if ((rep1 == rep) && num[i] != num[tmp1[0]])
{
tmp1[1] = i;
}
rep = -1;
}
if (num[tmp1[0]] > num[tmp1[1]])
{
int tmp = 0;
tmp = num[tmp1[1]];
num[tmp1[1]] = num[tmp1[0]];
num[tmp1[0]] = tmp;
}
printf("%d: %d %d", rep1+1,num[tmp1[0]],num[tmp1[1]]);
return 0;
}
最终提交代码结果如下图所示,只有例子正确,到了这一步之后就根据代码再进行修改,接下来面对的问题有:
1:每个数字都出现1次的情况
2:出现最多的个位数字大于2个
3:输入的数字越多,剥离的个位越多,数组溢出问题
我首先解决的是每个数字都出现一次,那么每一个个位数字都是出现次数最多的数字,题目要求按从小到大的顺序排列,那么我需要把存放剥离出来的个位数的数组里面的元素进行从小到大的排序,然后打印出来。
#include
int count = 0;
void div(int num[1000], int size, int x)
{
while (x != 0)
{
num[count] = x % 10;
x /= 10;
count++;
}
}
void sort(int arr[],int x)
{
int i = 0;
for (i = 0; i < x - 1; i++)
{
int j = 0;
for (j = 0; j < x - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
int tmp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = tmp;
}
}
}
}
int main()
{
int n = 0;
scanf("%d", &n);
int arr[1000] = { 0 };
int num[1000] = { 0 };
int i = 0;
int m = 0;
for (i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
for (i = 0; i < n; i++)
{
div(num, sizeof(num) / sizeof(num[0]), arr[i]);
}
int tmp = count;
int rep1 = 0;
int rep = -1;
int tmp1[1000] = { 0 };
for (i = 0; i < tmp; i++)
{
int j = 0;
for (j = 0; j < tmp; j++)
{
if (num[i] == num[j])
{
rep++;
}
}
if (rep1 < rep)
{
rep1 = rep;
tmp1[0] = i;
}
else if ((rep1 == rep) && num[i] != num[tmp1[0]])
{
tmp1[1] = i;
}
rep = -1;
}
if (rep1 == 0)
{
sort(num, tmp);
printf("%d: ", rep1 + 1);
for (i = 0; i < tmp; i++)
{
printf("%d", num[i]);
if (i < tmp - 1)
{
printf(" ");
}
}
}
else
{
if (num[tmp1[0]] > num[tmp1[1]])
{
int tmp = 0;
tmp = num[tmp1[1]];
num[tmp1[1]] = num[tmp1[0]];
num[tmp1[0]] = tmp;
}
printf("%d: %d %d", rep1 + 1, num[tmp1[0]], num[tmp1[1]]);
}
return 0;
}
代码2加了一个特殊情况判断,把每个数字只出现一次的情况列了出来,然后封装了一个冒泡排序的函数,把存放个位数的数组重新排序并打印。结果如下图所示,可见测试点3已经正确,现在已经能拿到15分啦,就剩下5分需要进行攻克了。
接下来需要修改的的才算是这个题最难的部分,现在代码大小大概100行左右,其实应该有更简单点的方法吧,我这个办法有点笨,现在我都想再加点.c文件和.h文件了。整个程序现在看着非常冗余,不过现在也不管这么多了,先实现功能。
#include
#include
int count = 0;
void div(int num[1000], int size, int x)
{
while (x != 0)
{
num[count] = x % 10;
x /= 10;
count++;
}
}
void sort(int arr[],int x)
{
int i = 0;
for (i = 0; i < x - 1; i++)
{
int j = 0;
for (j = 0; j < x - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
int tmp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = tmp;
}
}
}
}
int main()
{
int n = 0;
scanf("%d", &n);
int arr[1000] = { 0 };
int num[1000] = { 0 };
int i = 0;
int m = 0;
for (i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
for (i = 0; i < n; i++)
{
div(num, sizeof(num) / sizeof(num[0]), arr[i]);
}
int tmp = count;
int rep1[1000] = { 0 };
//int rep = -1;
int rep[1000];
memset(rep, -1, 1000);
int tmp1[1000] = { 0 };
for (i = 0; i < tmp; i++)
{
int j = 0;
for (j = 0; j < tmp; j++)
{
if (num[i] == num[j])
{
rep[i]++;//rep[i]记录num[i]出现多少次
}
}
/* if (rep1 < rep)
{
rep1 = rep;
tmp1[0] = num[i];
}
else if ((rep1 == rep) && num[i] != tmp1[0])
{
tmp1[1] = num[i];
}*/
//rep = -1;
}
//找到rep数组中最大的元素,最大的元素有几个
int count2 = 0;
int tmp3 = 0;
int flag2 = 1;
for (i = 0; i < tmp; i++)
{
if (rep[i])
{
flag2 = 0;
break;
}
}
if (flag2 == 1)//说明rep里面的元素全是0
{
sort(num, tmp);
printf("%d: ", rep[0] + 1);
for (i = 0; i < tmp; i++)
{
printf("%d", num[i]);
if (i < tmp - 1)
{
printf(" ");
}
}
}
else
{
int k = 0;
for (i = 0; i < tmp; i++)
{
int flag = 0;
int j = 0;
for (j = 0; j < tmp; j++)
{
if (rep[i] < rep[j])
{
flag = 1;
break;
}
}
if (flag == 0)
{
rep1[k++] = num[i];
tmp3 = rep[i];//重复最多几次
count2++;//记录几个重复最大的个数
}
}
sort(rep1, count2);
//3 3 3 4 4 4
//0 1 2 3 4 5
printf("%d: ", tmp3+1);
for (i = 0; i < count2; i=i+tmp3+1)
{
printf("%d", rep1[i]);
if (i < count2/(tmp3+1))
{
printf(" ");
}
}
}
/*if (rep1 == 0)
{
sort(num, tmp);
printf("%d: ", rep1 + 1);
for (i = 0; i < tmp; i++)
{
printf("%d", num[i]);
if (i < tmp - 1)
{
printf(" ");
}
}
}*/
/*else
{
if (tmp1[0] > tmp1[1])
{
int tmp = 0;
tmp = tmp1[1];
tmp1[1] = tmp1[0];
tmp1[0] = tmp;
}
printf("%d: %d %d", rep1 + 1, tmp1[0], tmp1[1]);
}*/
return 0;
}
代码3改了特别多整个程序算是焕然一新了,最主要的更新是拿变量存重复的次数改为用数组存重的次数,这次的程序就比较科学了,应该是较为符合题意,提交过后结果如下图:
由上图可以看出测试点1的答案已经正确了,但是输出的格式是错误的,经过我调试发现是输入一个数,这个数有重复的个位数时,末尾会多一个空格,然后就是测试点2,这种段错误一般是由于数组越界,我准备,把数组的大小调大一些再重新试一试。
#include
#include
int count = 0;
void div(int num[], int size, int x)
{
while (x != 0)
{
num[count] = x % 10;
x /= 10;
count++;
}
}
void sort(int arr[],int x)
{
int i = 0;
for (i = 0; i < x - 1; i++)
{
int j = 0;
for (j = 0; j < x - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
int tmp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = tmp;
}
}
}
}
int main()
{
int n = 0;
scanf("%d", &n);
int arr[1000] = { 0 };
int num[100000] = { 0 };//存放个位数
int i = 0;
int m = 0;
for (i = 0; i < n; i++)
{
scanf("%d", &arr[i]);//最大n 1000
}
for (i = 0; i < n; i++)
{
div(num, sizeof(num) / sizeof(num[0]), arr[i]);
}
int tmp = count;
int rep1[100000] = { 0 };
//int rep = -1;
int rep[100000];
memset(rep, -1, 100000);
//int tmp1[1000] = { 0 };
for (i = 0; i < tmp; i++)
{
int j = 0;
for (j = 0; j < tmp; j++)
{
if (num[i] == num[j])
{
rep[i]++;//rep[i]记录num[i]出现多少次
}
}
}
//找到rep数组中最大的元素,最大的元素有几个
int count2 = 0;
int tmp3 = 0;
int flag2 = 1;
for (i = 0; i < tmp; i++)
{
if (rep[i])
{
flag2 = 0;
break;
}
}
if (flag2 == 1)//说明rep里面的元素全是0
{
sort(num, tmp);
printf("%d: ", rep[0] + 1);
for (i = 0; i < tmp; i++)
{
printf("%d", num[i]);
if (i < tmp - 1)
{
printf(" ");
}
}
}
else
{
int k = 0;
for (i = 0; i < tmp; i++)
{
int flag = 0;
int j = 0;
for (j = 0; j < tmp; j++)
{
if (rep[i] < rep[j])
{
flag = 1;
break;
}
}
if (flag == 0)
{
rep1[k++] = num[i];
tmp3 = rep[i];//重复最多几次
count2++;//记录几个重复最大的个数
}
}
sort(rep1, count2);
printf("%d: ", tmp3+1);
for (i = 0; i < count2; i=i+tmp3+1)
{
printf("%d", rep1[i]);
if (i < count2 / (tmp3 + 1) - 1)
{
printf(" ");
}
}
}
return 0;
}
把数组的大小调大后,以及将输出格式问题-输出空格相关,修改之后得到了代码4,上传到PTA结果终于全部正确。
1:不会做的题,可以从例子开始,先实现特殊情况,再推广到普适的情况,一步一步的总结问题解决问题:
2:段错误问题,一般可能是数组越界,记得注意数组的大小。
3:程序产生的多个中间变量,可以用数组存放,后续操作起来很容易。