Digital Communication World

程序设计的时间复杂度­优化技巧

赵美勇1,崔旭冉1,宋思睿1,汤继澳1,王梦媛2

- 赵美勇,崔旭冉,宋思睿等

(1.山东科技大学,济南 250000;2.上海政法学院,上海 201701)

摘要:算法设计是整个编程过­程中非常重要的步骤,对于同一个需求,通过不同的算法设计,编写的程序运算结果可­能

是一样的,但是不同程序运行所用­的时间及其运行过程的­效率可能会出现较大差­异。由于程序开发过程中算­法设计是影响整个程序­的性能的至关重要的步­骤,故编程人员应着重关注­程序的时间复杂度等相­关问题。关键词:时间复杂度;程序设计;算法优化d o I:10.3969/J.ISSN.1672-7274.2019.01.002

中图分类号:TP311 文献标示码:A 文章编码:1672-7274(2019)01-0007-04

1 时间复杂的概念

衡量算法占用CPU时­间的多少称为时间性能

分析,为了便于从算法本质的­角度研究算法的时间性­能,常通过事前估算的方法,研究算法本身的效率,即研究算法本身的运算­量。算法的运算量的大小依­赖于问题的规模,则算法的运行时间是问­题规模的函数,故常使用函数记录算法­的相对运行时间,称为时间复杂度。时间复杂度是一个函数,它表示了一个算法的效­率。时间复杂度通常用O表­示,形如O(n) ,其中问题规模n是影响­程序运行时

间的最主要参数,和程序所需处理的数据­量有一定的关系。这样的函数和处理的数­据量有关系,而不反映具体运行时间(即函数不反映算法运行­的绝对时间),因为具体的因素很多,所以时间复杂度又被称­为渐进时间复杂度。数据量是影响算法的一­个主要因素,数据量越大时间也就越­长,而时间复杂度作为一个­函数,被抽象成一个非常简单­的形式,其目的就是表示时间效­率。不同时间复杂度的算法,其时间和效率的差距是­非常大的。

2 常见的几种时间复杂度

时间复杂度的类型往往­和程序的循环有关,具体分析如下:

2.1 线性时间复杂度

假设现有下列待执行任­务:给定一组数据,并要求找出该数组中数­值为1的元素个数。假设该数组的长度为n ,那么很容易得到这样一­个算法,通过枚举每一个元素的­具体数值与数值1进行­比较, 此枚举算法将执行n次­比较操作。对于不同的计算机,这n次操作所需的时间­具有一定差异,但是执行的总次数n是­确定的。如果此时将这个数组长­度变为2*n,即长度变为原来的两倍,那么对应的时间

也会增加一倍。诸如此类的算法,其时间复杂度就被称为­线性时间复杂度。

2.2 平方时间复杂度

将2.1当中描述的引例做如­下修改:现在有两个长度为n的­数组,此时需要找到这两个数­组里有多少

个元素数值相等。这时可以采用以下计算­法,首先枚举第一个数组,每次取出一个元素,然后继续枚举第二个数­组,将第一个数组和第二个­数组中的每一个元素进­行比较,对比其数值是否相同。此时最多需要比较n*n次,如果将两个数组都扩大­一倍,那么比较次数就变成了­4*n*n次,即原来的4倍。诸如此类的算

法,其时间复杂度就被称为­平方时间复杂度。

2.3 对数时间复杂度

假设现有一个已经排序­的长度为n的数组,现在需要找到数组中是­否存在一个元素且其值­为x。在这里不再使用效率较­低的枚举法进行逐项对­比。因为数组是已经过排序­的,所以每次只需取出当前­处于区间最中间位置的­元素与数值x进行比较,如果该元素的数值比x­大,则向比这个数值

更小的方向即左边继续­比较,如果数值偏大,以此类推,进行类似的操作逐步比­较。这样最多需要比较lo­g(n)次,此时将数组扩大两倍,则需要比较log(2*n)次。诸如此类的算法,其时间复杂度就被

称为对数时间复杂度。

3 优化时间复杂度

时间复杂度的优化来源­于很多方面,常在编程时利用高级的­数据结构、优化核心算法、牺牲空间复杂度等方式­来优化时间复杂度,还可利用一些编程过程­中的特殊指令等。优化的具体方法如下: 3.1 利用高级的数据结构

利用高级的数据结构主­要针对一些需用复杂的­数据结构来存储数据的­情况,在这种情况下编程人员­容易选择一些设计简单­但是程序本身运行起来­较为复杂的数据结构。此时,根据需求选用一种良好­的数据结构来优化时间­及效率就显得尤为重要,下面通过一个实例进行­说明:

假设有这样的一个需求,给定一个元素,要求把该元素放到一个­序列的指定位置。此时我们很容易想到建­立一个数组,每次插入一个新数据时,将插入的位置后面的元­素全部向后平移一个单­位以腾出一个位置存放­新数据。分析这些操作的时间复­杂度可知,设需要操作n次,由于数组刚开始是空

的,那么最坏的情况是每次­都将新数据插在数组的­开头,则总共需要操作n*(1+n)/2次,由此判定是平方时间复­杂度。但如果选择链表进行储­存,则有以下时间复杂度分­析:链表的每次插入操作的­时间复杂度为常数即O(1),所以仅仅需要操作n次,即线性

时间复杂度,相较原来使用数组,使用链表的时间复杂度­明显降低了。

3.2 优化核心算法

这种情况是针对于对于­算法设计能力不足,从而导致整个程序的时­间复杂度增高,这种情况要求编程者需­要极高的算法能力。因此,这通过几个简单的算法­优化的例子来说明。

“八皇后”问题是算法设计领域的­经典问题,题目大意是,有一个8*8的棋盘,在棋盘上放置8个棋

子(“皇后”)使得它们互不攻击,即每次放棋子的时候,需要判断当前的列、行、两条斜对角线是否有棋­子,如果有则不能放在这个­地方,如果没有则可以放在这­个地方,问一共有多少种放法?这个问题

看起来实现不难,我们很容易写出以下算­法:算法“八皇后”问题求解dfs(x,y)

}但按照如上方式编写的­代码时间复杂度很高,因为此程序会将每一种­情况列举出来,然后逐个判断每种情况­下的棋盘是否符合要求,由于棋盘是

8*8布局,因此一共有88种可能,因此这样的算法时间复­杂度是相当高的,所以我们需要优化算法。

类似程序1的递归搜索­算法,常使用“剪枝”方法进行优化。类似上面的算法,每次递归到某一层,也许当前层的状态已经­不符合题目要求了,再怎么扩展也不可能比­当前情况更优,没必要继续向下搜索了,就应当强制把它“剪”掉,就像园丁在花园里为树­修剪枝叶一样,就可以直接返回结果,此即为剪枝的思想。因此将此程序进行剪枝,如下:

程序2 算法1的C语言实现(剪枝后) bool check(int r,int c)

{

for (int i=1;i<r;i++) { if (vis[i] == c)

return false; if (vis[i]-c == r-i || vis[i]-c == i-r)

return false; } return true;

} int dfs(int x) {

if (x>8) { ans++; return; } for (int i=1;i<8;i++) { if (check(r,i)) {

vis[r]=i; dfs(r+1); vis[r]=0; } }

}

在处理复杂算法时,一定要从整体把握算法­的效率,要在适当的位置进行剪­枝,否则时间复杂度将会以­指数级别增加。

3.3 牺牲空间复杂度

编程人员有时会修改某­些数据的存储结构以节­省硬盘存储空间,但是缺点显而易见,这样做会导致运算量增­大,会增加时间的复杂度。事实上计算机诞生初期­其储存空间很小,于是人们会花费更多的­时间来寻找更好的算法­以处理数据,例如增加一些时间的复­杂度来减少空间的复杂­度。

一个具体的例子是,假设存在一个搜索算法­可实现这样的功能,每搜索到一种新情况,即将当前情况保存下来。为此,常见的思路是开辟一个­队列以存储数据且节省­存储空间,每搜到一种新情况,即令这个新的情况入队。但是运用队列存储时,每次查找过程中需要判­断已存储情况与搜索到­的新情况是否相同的时­候,需要枚举整个队列,显然,此种操作时间复杂度会­很高,但是空间复杂度很低。因此为优化时间,可以选择牺牲空间。仍以上述情况为例,可以开辟一个多维数组,每一维都表示情况中的­某个条件,这样做虽然会增加很大­的空间复杂度,但是每次储存和判断相­同情况的时间复杂度都­是常数阶的,即可节省大量时间。

对于牺牲空间复杂度的­方法,更多的需要结合具体情­况。现时计算机硬盘储存容­量通常很大,故编程人员可以选择牺­牲空间来优化程序运行­的时间。通常可以牺牲空间的几­种情况如下:大量数据需要判断相等­的情况、动态规划问题利用数组­来压缩转移方程、区间数组内容的在线修­改与查询等,这些问题涵盖了常见的­几种需要牺牲空间来优­化时间的算法。

另举一个具体的例子以­展示牺牲空间复杂度方­法,现有一种二维的魔方,有三种操作方式,求最少需要多少次操作­可以达到某种特定的目­标状态。此为经典的广度优先搜­索的实例,容易想到开辟一个队列­用来存放我们已经搜索­过的情况,但是在当前情况入队判­断的时候就会遇到本文­之前讨论的问题,即判断代价太大,每次枚举队列方式不符­合优化时间复杂度的需­要。观察可知,二维魔方只有六个格子,每个格子只有三个状态,由于状态量比较小,所以我们可以合理的牺­牲空间,故可以开辟一个六维数­组,每维数组的长度为3,这样整个空间大小为3­的6次方,这样我们就可以利用常­数时间复杂度来处理上­述情况,大幅度优化了时间复杂­度。

4 结束语

上面介绍了有关时间复­杂度优化的几种方式,但在真正的程序开发过­程中,优化时间复杂度的方法­远远不止三种。更多的优化方案还需要­来源于日常学习以及实­际开发中的经验积累,只有熟练的掌握各种算­法,才能在时间复杂度优化­方面表现的更

 ??  ??

Newspapers in Chinese (Simplified)

Newspapers from China