时间:2024-05-04
文/高向敏
(镇江第一外国语学校 江苏省镇江市 212000)
通俗地来讲,算法就是做某件事情或解决某一问题的方法、步骤、过程和程序,而算法优化是指对算法的有关性能进行优化。举个例子,大家熟知的田忌赛马的故事,在之前的比赛中,田忌总是以上等马对上等马,中等马对中等马,下等马对下等马,齐威王每一个等级的马都要比田忌的强,所以田忌总是输;后来孙膑给田忌出了个主意:比赛时,让他以下等马对齐威王的上等马,再以上等马对他的下等马,最后以中等马对他的下等马。比赛结束,田忌以三局两胜的战绩取得了胜利。同样的马匹,仅仅调换了比赛顺序,就得到了反败为胜的结果。从算法角度看,每场比赛的赛马次序编排都是一种算法,而孙膑的策略就是一种经过优化的算法。
同一问题可用不同算法解决,而一个算法的质量将影响到算法、程序直至软件的工作效率。衡量算法性能的主要指标有时间复杂度、空间复杂度、正确性、健壮性等。就单纯编程竞赛来说,竞赛要求每题的每个测试点数据应在1s内出运算结果,也就是基本语句的运算次数应该控制108以内,因此对于问题规模较大的题目,对算法进行合理优化是必不可少的;就宏观应用来说,假若将一个大的程序运用到实际生产生活中时,算法的执行效率将直接影响了生产效率,特别是,大数据时代到来,算法要处理的数据数量级越来越大,处理问题的场景也愈加千变万化,因此,为提升算法的效率,对算法进行优化也是必不可少的环节。
人们使用计算机处理问题时,首先要对实际问题进行抽象,运用数学思想创建数学模型,进而设计出解决的算法,然后再进行编程、测试、调整,这是一个实际问题运用计算机得以解决的过程。从这一过程可以看出,创建数学模型是前提,数学模型能够有效的把复杂的问题变简单,化繁为简,将一些复杂程度较高的、难以实现的编程问题,转化成单一的、便于运算的数学结构。因此,在进行算法优化分析时首要的就是要发挥数学理论知识的优势,构建数学模型,在此基础上设计并优化算法,求得问题的有效解决方式。数学建模不仅密切了数学、算法与计算机编程的关系,同时也直接影响了算法的正确性与性能。
当我们建立好数学模型后,将实际问题抽象化为单一简单的数学结构的时候,数学算法的使用对于计算机编程而言是必不可少的,是实现计算机编程算法优化的重要途径。如早期的数学算法代表——欧几里德算法,又名辗转相除法,是为了求得最大公约数的一种递回算法,每一步计算的输出值就是下一步计算时的输人值,这样的算法在处理大数时效率很高,也是计算复杂性理论的开篇。再如秦九韶算法、更相减损术、中国剩余定理等等,这些数学算法对编程算法优化都有着重大意义。除了诸如上述的经典数学算法之外,重要的数学方法如归纳法、演绎法等,或是程序设计者自己综合运用数学知识,充分挖掘实际问题中蕴含的数量关系,所寻找的数学规律、推导的数学公式、得出的数学结论,都是算法优化的重要途径。在此基础上设计的算法,往往使得原本难以解决的问题得以解决,原本已解决的问题得以高效解决。
图1:各因子对应关系
图2
图3:行列值与所在圈数之间的关系图
图4
总之,数学思想是连接问题与算法的一座桥梁,有些问题利用这座桥可以更为方便快捷地往返于河两岸,而还有一些问题,如果不利用这座桥可能根本无法到达河的对岸,因此,借助数学思想分析问题是进行算法优化的重要途径。
下面结合编程教学中的几个具体实例,践析数学思想在算法优化中的应用策略。
求n以内的完全数。
表1:不同方法运行时间比较
表2
表3
完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数。它所有真因子(即除了自身以外的约数)的和,恰好等于它本身。第一个完全数是6(1+2+3=6),第二个完全数是28 (1+2+4+7+14=28)。若求n内的完全数,需要对2-n以内的每个数判断是否是完全数(1不是完全数),因此本题关键在于如何判断一个数i是否是完全数。对于这个问题可以用不同的数学方法来解决。
方法一:最直接的方法,从1到i-1每个数依次判断其是否是i的真因子,若是则累加求和至sum,若sum=i,则说明i是完全数。
方法二:根据数学常识,对于某一整数i来说,其最大因子为i/2,在i/2~i-1范围内没有数据可以整除此数。据此,我们可以把遍历范围缩小至1~i/2,这样程序效率可提高一倍。
方法三:进一步思考,若j是i的一个因子,则i/j一定也是i的因子,若已知1,2,4,5,10是100因子,相应地即可得出100,50,25,20,10也是其因子(如图1所示),据此,我们可以把遍历范围缩小至1~即可。
方法三改进:sqrt函数一个求平方根的库函数,函数调用有一定的时间损耗,其次,内部是浮点数运算,效率也不高,乘法的效率比除法要高的多,因此我们对循环结束条件又做了一部分改进(j*j<=i),程序效率会大大提高。
为了更加直观对比各算法的运行效率,我们分别对其进行了n=10000,以及n=1000000的测试,程序运行时间对比如表1。
利用简单的数学常识,缩小数据范围,对程序的局部进行优化,如对程序循环次数简化等,从而达到提高程序工作效率的目的。
一个n行n列的螺旋矩阵可由如下方法生成:从矩阵的左上角(第1行第1列)出发,初始时向右移动;如果前方是未曾经过的格子,则继续前进,否则右转;重复上述操作直至经过矩阵中所有格子。根据经过顺序,在格子中依次填入 1,2,3,...,n2,便构成了一个螺旋矩阵。图2是一个 n = 4 时的螺旋矩阵。现给出矩阵大小 n 以及i和j,请你求出该矩阵中第i行第j列的数是多少。
方法一:最直接解法,建立一个二维数组a依次存放各个矩阵数据,然后输出a[i][j]的值即可。而当n=30000时,需要建立30000*30000的二维数组,结果会发生数据溢出且超出内存上限。
方法二:我们可采用类似贪吃蛇的方法,让它在n*n个方格内自外向内逐格移动,控制其右转的方向,直到到达i行j列位置,整个过程中移动步数即为求解值。
方法三:在上一个方法中,若遇到极端情况——当n=30000时候,求第15001行15000列的数是多少,需要移动次数为900000000,显然太慢,因此我们需要进一步优化。考虑到贪吃蛇总是从外围一圈圈地向目的地前进,而每一圈刚好是一个正方形,我们可以先计算外围各圈正方形的周长之和,再让贪吃蛇从目的地所在圈的的左上角出发,计算其从出发地到目的地的长度就可以了。鉴于此,我们需要寻找如下几个数学规律:
(1)第i行j列位于第几圈(假设为第x圈)
(2)前x-1圈,每一圈有多个数字;
(3)第i行j列位于第x圈的第几个。
由图3得数学规律:第i行第j列的所在的圈数x一定是(i,j,n+1-i,n+1-j)这四个数中的最小值;第1圈有(n-1)*4个数字,第2圈有(n-3)*4个数字,……,则第k圈有(n-2*k+1)*4个数字;我们只需要从所在x圈的左上角(x,x)位置出发,走到目的地(i,j)即可,最多走一圈,各算法效率比较如表2所示。
建立数学模型,寻找各数据之间内在的数学关系,归纳数学规律,在此次基础上优化算法,往往大大提高算法性能。
如图4,一条狭长的纸带被均匀划分出了n个格子,格子编号从1到n。每个格子上都染了一种颜色colori(用[1,m]当中的一个整数表示),并且写了一个数字numi。
定义一种特殊的三元组:(x,y,z),其中 x,y,z 都代表纸带上格子的编号,这里的三元组要求满足以下两个条件:(1) x,y,z都是整数,x 方法一:最直接的解法,根据x,y,z的关系 y-x=z-y,双重循环枚举x,y,当满足条件colorx=colorz时求得该三元组分数并累加起来。 方法二:方法一中如果n数值较大时,非常慢,因此需要充分挖掘数据之间的关系,本题我们可以借助数学公式推导:根据题意可知,三元组的分数仅与x,z有关,与y无关.假设编号为x1,x2,x3的元素彼此间都符合题目要求的2个条件,则它们必定奇偶性相同、颜色相同。我们假设同颜色元素个数k=3,则其三元组分数之和表示为: 因此,我们只需要找出每一种颜色下编号同为奇数三元组分数之和、编号同为偶数三元组分数之和即可。如表3所示。 充分挖掘问题中的数据关系,借助数学公式推导,得出结论,并在结论基础上从整体架构、设计算法,从而提高算法性能,达到事半功倍的效果。 计算机的学习离不开数学理论与知识的学习和运用,数学算法是计算机编程的基础,数学思想作为沟通问题与编程实现的一座桥梁,有着极其广泛的应用。它不仅可以直接为解题提供思路,如果与其他算法或者思想相结合,还能够起到很好的辅助作用。通过数学模型的建立,利用数学算法对编程逻辑进行分析设计,不断优化数学算法,降低其时间复杂度、空间复杂度。在你觉得“山穷水复疑无路”时,不妨用数学的角度重新审视问题,也许就会“柳暗花明又一村”。4 结束语
我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自各大过期杂志,内容仅供学习参考,不准确地方联系删除处理!