对于算法分析最重要的是分析运行时间。在影响程序运行时间的因素中,除了某些超出所有理论模型范畴的因素诸如所使用的编译器和计算器之外,主要的影响因素是所使用的算法和对该算法的输入。
为了对运算时间进行简化分析,我们采用约定:不存在特定的时间单位。因此我们抛弃一些前导的常数和低阶项,从而计算大O的运行时间,由于大O是上界,绝不要低估程序的运行时间。
例:计算∑ i³
public static int sum(int n){
int sum;
⑴ sum = 0;
⑵ for(int i = 1; i <= n; i++){
⑶ sum += i * i * i;
}
⑷ return sum;
}
分析:所有的声明均不计时间。第一行赋值语句和第四行返回值语句各占一个时间单位。第三行运行一次占4各时间单位(一次赋值,两次乘法,一次加法),总共运行N次占4N个时间单位。第二行占(一次赋值,N+1次比较,N次自加)共2N+2个时间单位。忽略调用方法和返回值的开销,得到总量是6N+4个时间单位。因此我们说该方法是O(N)的。
由于我们有了大O的结果,因此就存在许多可以采取捷径而不影响最后运行结果的方法。例如在第三行中我们无需知道运行一次到底占几个时间单位,我们只要知道它是O(1)的就行,至于赋值语句等与for循环比起可以忽略最后得到的结果还是O(N)。所以为了简化分析,我们不必计较具体开销,这使得我们得到一般法则。
法则一——for循环:
一个for循环运行时间至多是该for循环内部那些语句(包括测试)的运行时间乘以迭代次数。一般情况下由于大O内部任何简化都是可能的,所以一般简单的for循环得到的结果是O(N)的。
法则二——嵌套的for循环:
从里向外分析循环。在一组嵌套循环内部的一条语句运行时间为该语句的运行时间乘以该组所有的for循环大小的乘积。例如双重for循环内部有一条赋值语句,则结果为O(N²)。
法则三——顺序语句:
将各个语句的运行时间求和即可。(O(f(N))+O(g(N))= max(O(f(N)),O(g(N))
法则四——if / else语句:
对于程序片段
if(条件)
语句
else
语句
一个if / else语句的运行时间不会超过判断的运行时间加上两个语句中运行时间较长的那个语句的运行时间。