C语言博客作业04--数组
1.本章学习总结
1.1 思维导图
1.2 本章学习体会及代码量
1.2.1 学习体会
- 本章主要学习了函数的相关知识,数组是最基本的构造类型,它是一组相同类型数据的有序集合,数组中的元素在内存中连续存放,每个元素都属于同一种数据类型,用数组名和下标可以唯一地确定数组元素。数组就像一个地区,将一堆数据存入房间,按门牌号找到数据,管理方便,可以让一批相同类型的变量使用同一个数组变量名,用下标相互区分,它能使表达简洁、可读性好。由于数组的特点是多,所以结合前面的循环结构很好地处理了数组,再通过巩固选择法和冒泡法的排序技巧,能将解题思路变得更清晰。
- 数组的学习使我们从单一的几位数或几个数跨向繁杂的多位数或多个数,长字符的处理也有了很好的解决方法,这使得我们在自己编写一个大程序的道路上更进了一步。在往后的学习中,还需要不断巩固以前的知识,和新知识结合运用,这样才能让自己不断进步,在编程的道路上fighting!
1.2.2 代码累计
2.PTA总分
2.1截图PTA三次题目集的排名得分:
2.2 我的总分:
一维数组:200
二维数组:105
字符数组:150
总分:455
3.PTA实验作业
3.1 PTA题目1
读入数据,检查是否有重复的数据。如果有,输出“YES”;如果没有,则输出“NO”
3.1.1 算法分析
定义n为元素的个数,i为计量数
输入n
定义数组Numbers[n]
定义静态数组Count[100001]
for i=0 to n do //用于输入各数字
输入Numbers[i]
end for
for i=0 to n
Count[Numbers[i]]++//在对应数组Count的位置加一
end for
for i=0 to 100000 do
if Count[i]>1 then //当有元素超过1时,输出YES
输出"YES"
返回0
end if
end for
输出"NO"
返回0
3.1.2 代码截图
3.1.3 PTA提交列表及说明
- Q1:部分正确的情况为有的测试点运行超时
- A1:起初用的方法是只定义一个数组,通过每个元素逐一比较,造成很多不必要的计算,所以运行超时。通过询问同学得知,用两个数组的方法计算会简便,所以我又加了一个静态数组,通过Numbers数组出现的数字代入Count数组的位置进行统计,最后直接判断当有元素超过1即出现次数超过1次时,输出“YES”,否则输出“NO”。
- Q2:对于这类要求不能有过多多余运算的题目
- A2:像第一次使用的普通方法在这类题目中会由于过多运算而运行超时,此时就可以转化思维,再加一个数组,以二维对应的方法通过一次循环就能将数字统计,大幅提高效率且直观易懂。本题可以在判断最终统计时,通过flag赋值判断是否输出;而我则是,如果有一项超过了1,就i能输出“YES”,并直接返回0,也节省了运算量。
3.2 PTA题目2
简单的图书借阅统计,借书时输入书号和S,还书时输入书号和E,输入0时输出当天的借书次数和平均阅读时间
3.2.1 算法分析
定义n为天数,temp用来判断临界值,sum为总阅读时间,flag为成功借书次数
定义number为书号,hour和minute分别为小时和分钟,time为总时间
定义i和j为计量数
定义静态数组a[1001]储存借书记录
定义静态数组b[1001]储存还书记录
定义字符变量op为借书符号
输入n
for i to n do//天数划分
for j=1 to 1001 do a[j]=0//对数组a的值初始化为0
for j=1 to 1001 do b[j]=0//对数组b的值初始化为0
sum=0//初始化阅读时间
flag=0;//初始化借书次数
while(1)
输入"number op hour:minute"
if number==0 then break//当输入0时,当天结束
time=hour*60+minute
if time==0 then temp=1//作为临界值的标志
switch 判断 op
若'S'则a[number]=time 退出循环
若'E'则
if a[number]!=0||temp==1 then //判断是否有借出
b[number]=time
sum=sum+(b[number]-a[number])
flag++
a[number]=b[number]=0 //初始化该书号的记录
temp=0
end if
退出循环
end switch
if flag==0 then printf("0 0\n") //当无借书时,避免除数为0而单独判断
else printf("%.0f %.0f\n",flag,sum/flag)
end while
end for
3.2.2 代码
3.2.3 PTA提交列表及说明
- Q1:题目要求复杂多向,要求记录数据还要筛选数据进行储存
- A1:向同学请教得知,重复的借书记录以第二次为准。定义两个静态数组分别储存借书和还书的记录,如果出现两次借书,则会覆盖上次借书的记录;在还书的记录上要求必须要有借书的记录才能录入,即时间大于0,同时完成还书后对借书记录清零,方便二次借书的储存;但是由于在0时借书也不能进行录入,故用temp作辅助判断;需要注意当没有人借书时,平均阅读时间的算式除数为0,要分别讨论。
- Q2:对于这类复杂多要求的双条件数据的题目
- A2:设立两个数组分别储存两种数据,注意筛选合法的数据,也要注意极端的数据,像数值为0、除数为0等类似情况,对其联系并计算,必要时多采用像flag的判断辅助值,可以让特殊情况更容易判断;数据的及时初始化也是程序的关键。
3.3 PTA题目3
输入2个大数,每个数的最高位数可达1000位,求2数的和
3.3.1 算法分析
定义i,j,k为计量数
定义len1,len2,len记录元素位置
定义两个静态字符数组num1[1000]和num2[1000]输入大数
定义两个静态整形数组Num_A[1000]和Num_B[1000]逆序输入大数
输入num1和num2
for len1=0 to num1[len1]!='\0' do len1++ //判断第一个大数的位数
for i=0,j=len1-1 to j>=0 do //把大数转化为数字并倒放
Num_A[i]=num1[j]-'0'
i++,j--
end for
for len2=0 to num2[len2]!='\0' do len2++ //判断第二个大数的位数
for i=0,j=len2-1 to j>=0 do //把大数转化为数字并倒放
Num_B[i]=num2[j]-'0'
i++,j--
end for
把len1和len2中最大的数赋值给len
for k=0 to k<len do
Num_A[k]=Num_A[k]+Num_B[k]
if Num_A[k]>=10 then //处理进位
Num_A[k]=Num_A[k]-10
Num_A[k+1]++
end if
if Num_A[len]!=0 then //考虑最高位进一的情况
printf("%d",Num_A[len])
end if
for len-- to len>=0 do //逆序输出结果
printf("%d",Num_A[len])
end for
end for
3.3.2 代码
3.3.3 PTA提交列表及说明
- Q1:在模拟计算时,两个大数的位数不同使得运算不能直接进行
- A1:定义两个数组负责将原有的数组倒序存放,这个过程需要知道两个数的位数,再以位数较大的数为基准进行倒序排放
- Q2:通过数组输入字符来计算的目的是数字过大超出变量定义的范围
- A2:需要用数组把每个数字存入,再模拟数字计算进行逐位运算,需要注意的是同位相加,满十进一的基本运算原理;最后由于判断位数时的限制,无法将最高位是否有进一的情况区分,如多设一个单元则会在无进一的情况下多输出一个0,不多设一个单元则会使数字溢出,故单独判断最高位是否进一,将结果逆序准确输出
4.代码互评
4.1 代码截图
-
同学代码
-
我的代码
4.2 二者的不同
相同点:
1.都是定义两个数组进行借书和还书的记录,用循环语句来记录不同天数,switch区分借书和还书的字符。
2.对于合法数据的判断都有特殊变量进行判断,对于像除数不能为0的特殊情况进行分开讨论。不同点:
1.同学以输入数据为一次大循环,先输入一串数据,通过输入的数据执行不同命令,再进入下一串数据的循环;而我则是以每一天为一次大循环,在改天中的所有数据进行一次统计和计算,再进入下一天的循环。
2.同学定义一个二维数组来区别是否是合法记录,数据捆绑较为直观;而我则是定义一个一维数组,用flag值辅助判断是否是合法记录,变量分开较为清晰。缺点在于我的方法不能区分在时间为0的情况,需要另定义一个变量来判断。