博主的数据结构刷题笔记,自己的练习记录,供大家参考,文中所列代码均经反复调试或OJ系统判定通过,如仍有疏漏欢迎大家留言指正,文中算法优化不足的地方欢迎大家留言交流,感谢。
目录
1.题目
写出这个数 (20 分)
读入一个正整数 n,计算其各位数字之和,用汉语拼音写出和的每一位数字。
2.输入输出要求
3.题目解析
这道题有一个初学者容易忽视的坑,就是本题的输入数据的值有可能会非常大,最大可能到10^100,这样的数是任何整数类型都存不下的,因此需要用字符串去存储一个整数,由此带来的问题是处理过程中会有一些小麻烦,要进行ASCII码的转换。
3.1 输入数据
输入一个很大很大的整数,大到任何整数类型都存不下(会溢出),因此程序要考虑把数字当做字符串去处理。
3.2 算法处理
首先,要能读取并准确存储一个字符串,于是写下这样的C代码:
#include <stdio.h>
#define N 50 //假设最大的数的位数最大到49位(最后一位是字符串的结束符\0)
int main(void)
{
char data[N];
int i = 0;
scanf("%s",data);
printf("data: %s",data);
return 0;
}
测试了一下没有问题,上面的代码没什么好解释的,就是最基本的变量、输入输出函数的简单应用。
下面开始写一个循环,遍历并处理这个字符串中的每一个字符,遍历过程要求出这个数字的和是多少,因此需要定义一个变量sum用作求和。C代码如下:
#include <stdio.h>
#define N 50 //假设最大的数的位数最大到49位(最后一位是字符串的结束符\0)
int main(void)
{
char data[N];
int sum = 0;
int i = 0;
scanf("%s",data);
while(data[i]!='\0'){ //遍历整个字符串
sum+=data[i]-'0'; //对每一个字符进行转换,使每个字符变成所对应的数字
i++;
}
printf("sum = %d\n",sum);
printf("data: %s",data);
return 0;
}
比上面的代码多了一个while循环,循环条件是只要没有遍历到字符串的末尾就继续遍历。处理过程就是ASCII码转换成对应的数字并加到sum上。最后循环结束后输出了原数据和各个位求和的结果。自己进行了简单点的测试,没问题。
上面的程序和最终结果已经很靠近了,就差最后一步用汉语拼音输出一下结果了。
下面最后一个要解决的问题是,如何取得这个求和结果sum的各个位是多少,我的思路是首先将sum倒序存储在一个数组里,即如果sum为12300,倒序存储后变成00321(注意这里不能用一个整数类型去存,不然前面的0都没有了),然后挨个输出数组中的数字对应的字符串就好了,注意每个字符串之间要多输出一个空格,最后一个数字的后面没有空格。
3.3 输出数据
输出数据是一组字符串,即用汉语拼音表示每个数字。
3.4 涉及到的主要知识点
1.字符串的读取和输出,字符串的基本操作。
2.ASCII码的知识,可以参考百度百科:https://baike.baidu.com/item/ASCII/309296?fr=aladdin
3.5 Java语言实现源代码
用java语言实现该题目,可以不用字符串存输入数据了,直接用BigInteger更方便,同样拼音数组用String类型比C语言的二维数组更方便。除此之外的算法处理部分都是一样的。
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
BigInteger num = sc.nextBigInteger();//num为读取到的输入数据
sc.close();
char[] data = num.toString().toCharArray();//直接将数字转为字符串,便于迭代
int sum = 0;
int[] sum_array= new int[50];
String numdata[] = { "ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu" };
int i = 0;
for (int j = 0; j < data.length; j++) {
sum += data[i] - '0'; // 对每一个字符进行转换,使每个字符变成所对应的数字
i++;
}
i = 0;
//倒序保存求和值sum
while (sum != 0) {
sum_array[i] = sum % 10;
sum /= 10;
i++;
}
//计算结果输出部分
System.out.print(numdata[sum_array[i-1]]);
for (int j = i - 2; j >= 0; j--) {
System.out.print(" "+numdata[sum_array[j]]);
}
}
}
上面代码通过了PAT OJ系统的测评。
3.6 C语言实现源代码
这段C语言代码算法思路和上面java代码一毛一样,我在本地windows测试了很多组数据都没问题,但是反复修改了半天,提交上去一个都通过不了,貌似是我用的编译器(DEV-C++)和PAT系统上的GCC编译器有较大的差别。果然是C语言有很多方言,跨平台性不好。
#include<stdio.h>
#include<string.h>
int main(void)
{
char data[100];
int sum = 0;
int i = 0,j;
char sum_array[20];
char numdata[][10]={"ling","yi","er","san","si","wu","liu","qi","ba","jiu"};
gets(data);
while(data[i]!='\0'){ //遍历整个字符串
sum+=data[i]-'0'; //对每一个字符进行转换,使每个字符变成所对应的数字
i++;
}
i = 0;
while(sum!=0){
sum_array[i] = sum%10;
sum/=10;
i++;
} //反序存储
for(j=i-1;j>=0;j--){
printf("%s",numdata[sum_array[j]]);
printf(" ");
}
printf("\b");
return 0;
}
4.总结
这道题的一个坑就是对输入数据的处理不能用整数类型去处理,而要用字符串类型。其余之处都是字符串的常规操作了。
疑问:还没搞清楚到底C语言代码有何问题,通过不了OJ系统的测试。留在以后慢慢解决。Java大法好。