前阵子有同学跟我讨论,怎么这个问题用递归方法(O(n^2))比非递归方法(O(n)解决时间还快?按照算法复杂度来看,前者比后者慢啊,这怎么解释?
其实,算法复杂度O()的表示方法是参考很多因素的,不能因为一两个例子而决定。
首先,一个算法的好坏,我们肯定不能做最好情况的打算,比如任何一种搜索算法,假如第一个元素就是我们要搜索的元素,那不管何种搜索算法,时间似乎都差不多快,没什么多大的比较意义。
那么,算法的性能就当然用最坏情况来比较(也有平均情况下考虑的,但这个平均比较模糊)。例如,要搜索的元素,在数据库中压根就没有,这是最坏情况了吧。这时候,算法的性能就可能有点显露出来了,为什么说有点呢?因为就像前面一开始的例子,O(n^2)与O(n)的算法复杂度,在实际情况中并不完全是这样的。
先来说说O()表示方法,O表示一个函数的上限,也就是假设n变得无穷大的时候,来考察算法的性能。相信高中的时候,大家都知道,函数的求导,也就是函数值y的增长率,是会随着x的值不断变化的。比如,y1=x^2,y2=5*x,这两个函数,当x=2的时候,y1=4 < y2=10,当x=5的时候,y1=y2=25,当x>5的时候,将会永远存在y1>y2。这就是增长率的问题。O()表示方法也是这样的,只是把n考虑到无穷大的时候,常数可以忽略,比如一开始我同学问我的问题里面,后者非递归算法,可能不是O(n),而是O(10*n),只是n无穷大的时候,10简直是打酱油的,忽略不计(所以写成O(n))。所以说,不能在某一个程序中确定n值的时候,拿O()复杂度来说事。比如,具体的程序中,n=5的话,O(n^2)当然比O(10*n)来得快,这也是解决了前面我的同学的困扰。
精确衡量算法是很难的,因为算法里面,包括语句运行,包括数据处理,包括空间复杂,很多因素。所以,采用什么算法,不能只根据O()表示法来确定,假如A算法特点:语句执行快,数据空间复杂。B算法特点:语句执行慢,数据空间简单。那如果一个程序里面是需要很少数据的,当然就采取A算法,因为程序的数据少,更加符合这个算法的特性。
所以,采用什么算法,具体分析各种因素而定。