关于运行时间中的对数

关于运行时间中的对数

书中的翻译是这样的:如果一个算法用常数时间(O(1))将问题的大小削减为其一部分(通常是1/2),那么该算法就是O(logN)。另一方面,如果使用常数时间只是把问题减少一个常数(如将问题减少1),那么这种算法就是O(N)的。

翻译很拗口,不过好在下面给出了三个例子:对分查找、欧几里得算法和取幂运算,再结合前面的最大子序列和问题,我的理解是这样的:无论是用循环还是递归,程序每次执行时都将变量减半(上面说的削减为一部分),并且循环和递归之外的语句是常数阶复杂度O(1),也就是有确定的执行次数,这样的程序往往是对数阶的。

至于原理,直观上来讲,比如开始变量为N,每次变为1/2,需要logN次就可以让变量从N变到1,此时也就是基准情况,所以执行次数就是logN了。更加准确的分析是使用递推公式,例如上面的最大子序列和,递归之外的语句复杂度为O(N),设求解大小为N时时间为T(N),可以列出递推公式:

T(1)=1;

T(N)=2T(N/2)+O(N);

把这里的O(N)用N代替可以算出T(N)=NlogN+N=O(NlogN)

当然这个程序是所谓的“分治”方法,复杂度为NlogN的,并不是logN,但分析方法都是类似的,即通过递推公式。

例如:最后的取幂运算问题,算法如下:

long int pow(long int x, unsigned int N)
{
if(N==0) return 1;
if(N==1) return X;
if(IsEven(N)) return Pow(X*X,N/2);
else return pow(X*X,N/2)*X;
}

这里面如果用乘法的次数衡量运行时间,或者连判断也算上,总之每次递归内部都是O(1),列出的递推式:

T(1)=1;

T(N)=T(N/2)+O(1);

把O(1)当1来算,可以得出来T(N)=logN+1=O(logN)。

不过这里通过递推得到公式都是写出前几项归纳的。。。至于真正怎么去算这个公式是数学问题。。书里预言了第七章会讲。。

(《数据结构与算法分析 C语言实现》Mark Allen Weiss

你可能感兴趣的:(关于运行时间中的对数)