第八章 数组 学习感想
本章中,我主要学到了如何使用数组,包括一维数组、二维数组的定义及初始化、数组的排序和查找等知识。
我学到了一个很巧妙的查找方法——二分查找法。这就好比是要找一本书的某一页,先翻开它的任意一页,如果这一页比目标页大(小),那么就向前(后)翻,后面的步骤亦是如此,就这样把查找范围不断缩小,直到达到目的。使用这种方法的其中一个好处就是,可以避免超时。就拿作业4中的一道题来讲:
题目要求在给定的n个互不相等的正整数中,寻找可以形成a*b=c的等式(a,b,c互不相等)的数目。
我最开始是使用了三层嵌套的for循环,并且每一次循环都从0开始。这样的程序虽然可以得到正确的结果,但不幸超时了,因为数组中的数的个数最多可以达到1000个,像我这样循环可能会循环到10的9次方次。于是我又把原数组排序,并使每层循环从不一样的地方开始:
for(a=0;a<n;a++)
for(b=a+1;b<=n;b++)
for(c=b+1;c<=n;c++)
这样总算可以节省一部分时间,但仍不是最好的方法。最后,在老师的指导下,我发现可以使用二分查找的方法:让m[c]=m[a]*m[b],之后在数组里面查找m[c]。此时,要是m[a]*m[b]的值在数组里面,sum值就加1。这样最多循环10的7次方次,可以节省很多时间。
另外,做本次作业时,我也遇到了一些其他的问题,并且有了一些感悟。比如:
1.数组的名字不能跟其他变量定义相同,虽然是很小儿科的问题,但是我经常在此犯错。
2.在做“做游戏”一题的时候,我遇到一个令自己头疼的地方,就是循环到最后一个数的时候总是出问题,不能得到加上第一个数的解,而是变成了一个随机的数。后来我发现,我把循环写成了:
for(i=1;i<=M;i++)
a[i]=a[i]+a[i+1]%100;
if(i= =M)
a[i]=a[i]+a[1]%100;
我原以为因为a[M+1]不存在,那样a[i]=a[i]+a[i+1]%100;就会因为执行不下去了而自动停止,开始执行if(i= =M)a[i]=a[i]+a[1]%100;但其实它是报错了。应该分为
if(i= =M)
a[i]=a[i]+a[1]%100;
else
a[i]=a[i]+a[i+1]%100;
但即使是这样也不行,因为此时if(i==M)时加上的a[1]已经不是之前的a[1]了,它已经加上了a[2]%100。要解决这个问题,就要再定义一个新的数组,使它随着数组a更新,而且其中的a[i]不是上轮的,而是本轮加数之前的a[i]。
遇到错误了,先要自己反复研读(走查,甚至在纸上写出每一步的循环过程),分析代码有没有问题。有时怎样也找不出错误,看的头疼,是因为没有跳出之前的代码,一直在原来的代码中,读来读去也感觉没有问题。这时要及时跳出自己的代码,回去再看看题,而看题的时候,要当成新题来读,以免陷入原来的代码中。同时要多次回去分析题目要求,因为在分析原题的过程中,往往会产生新的想法。然而,遇到问题也不要走另一个极端——反复想也想不出来,仍然反复的想,这样虽然看起来很坚持,但也浪费时间。
另外,检查程序的时候,如果有数据,要首先检查数组的编号是否一致、语法是否有错误。
但是再怎样细致的检查都不如最初写代码时的仔细来的重要,所以不论写什么样的代码,都应该仔仔细细,不在细节上犯马虎。