时间复杂度计算
算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。这是一个关于代表算法输入值的字符串的长度的函数。时间复杂度常用大O符号表述,不包括这个函数的低阶项和首项系数。
求解算法的时间复杂度的具体步骤是:
⑴ 找出算法中的基本语句;
算法中执行次数最多的那条语句就是基本语句,通常是最内层循环的循环体。
⑵ 计算基本语句的执行次数的数量级;
只需计算基本语句执行次数的数量级,这就意味着只要保证基本语句执行次数的函数中的最高次幂正确即可,可以忽略所有低次幂和最高次幂的系数。这样能够简化算法分析,并且使注意力集中在最重要的一点上:增长率。
⑶ 用大Ο记号表示算法的时间性能。
将基本语句执行次数的数量级放入大Ο记号中。
如果算法中包含嵌套的循环,则基本语句通常是最内层的循环体,如果算法中包含并列的循环,则将并列循环的时间复杂度相加。例如:
for (i=1; i<=n; i++)
x++;
for (i=1; i<=n; i++)
for (j=1; j<=n; j++)
x++;
第一个for循环的时间复杂度为Ο(n),第二个for循环的时间复杂度为Ο(n2),则整个算法的时间复杂度为Ο(n+n2)=Ο(n2)。
常见的算法时间复杂度由小到大依次为:
Ο(1)<Ο(log2 n)<Ο(n)<Ο(nlog2 n)<Ο(n^2)<Ο(n^3)<…<Ο(2^n)<Ο(n!)
Ο(1)表示基本语句的执行次数是一个常数,一般来说,只要算法中不存在循环语句,其时间复杂度就是Ο(1)。
Ο(log2n)、Ο(n)、Ο(nlog2n)、Ο(n2)和Ο(n3)称为多项式时间,而Ο(2n)和Ο(n!)称为指数时间。计算机科学家普遍认为前者是有效算法,把这类问题称为P类问题,而把后者称为NP问题。
这只能基本的计算时间复杂度,具体的运行还会与硬件有关。
上面的这部分内容是比较可靠的,理解的时候,可以参看着下面的这部分内容。
在计算算法时间复杂度时有以下几个简单的程序分析法则:
- 对于一些简单的输入输出语句或赋值语句,近似认为需要O(1)时间
- 对于顺序结构,需要依次执行一系列语句所用的时间 可采用大O下"求和法则"
求和法则:是指若算法的2个部分时间复杂度分别为 T1(n)=O(f(n))和 T2(n)=O(g(n)),则T1(n)+T2(n)=O(max(f(n), g(n)))
特别地,若T1(m)=O(f(m)),T2(n)=O(g(n)),则 T1(m)+T2(n)=O(f(m) + g(n))
- 对于选择结构,如if语句,它的主要时间耗费是在执行then字句或else字句所用的时间,需注意的是检验条件也需要O(1)时间
- 对于循环结构,循环语句的运行时间主要体现在多次迭代中执行循环体以及检验循环条件的时间耗费,一般可用大O下"乘法法则"
乘法法则:是指若算法的2个部分时间复杂度分别为 T1(n)=O(f(n))和 T2(n)=O(g(n)),则T1*T2=O(f(n)*g(n))
- 对于复杂的算法,可以将它分成几个容易估算的部分,然后利用求和法则和乘法法则技术整个算法的时间复杂度
另外还有以下2个运算法则:
(1) 若g(n)=O(f(n)),则O(f(n))+ O(g(n))= O(f(n))
(2) O(Cf(n)) = O(f(n)),其中C是一个正常数
可以用以上法则对下面程序段进行简单分析
①for (i=0; i<n; i++)
② for (j=0; j<n; j++)
{
③ c[i][j] = 0; / * T3(n) = O(1) */
④ for (k=0; k<n; k++)
⑤ c[i][j]= c[i][j]+ a[i][k]* b[k][j]; / * T5(n) = O(1) */
}
第①条与②③④⑤是循环嵌套T1(n)*T2(n)* (T3(n)+ T4(n)* T5(n))= O(n*n(1+n))=O(n*n*n) 即为整个算法的时间复杂度
O(1)<O(log2 n)<O(n)<O(n log2 n)<O(n^2)<O(n^3)<O(2^n)
例题:
Which of the choices below correctly describes the amount of time used by the following code?(下面哪个选项正确地描述了代码运行的调度次数?)
解答:
x=x+1;是循环最内侧的代码,其时间复杂度最高,所以只求这句代码的复杂度即可。
从内到外看,k循环从1==20开始每次变成原来的2倍,一直到大于n-1,所以循环体运行次数为|log(n)|,时间复杂度为O(log(n))(计算机中log默认底数是2);
j循环从1开始每次递增n/2,一直到n-1,第一次递增之后j变成(n+2)/2,第二次递增j则是n+1,所以应该是循环了2次,但是时间复杂度还是O(1),因为常数次数的时间复杂度都是O(1)的;
i循环从1开始,每次增1一直到n-1,所以循环体运行n-1次,时间复杂度O(n)。
最后相乘得到总的时间复杂度为O(n*1*log(n))=O(n*log(n)),
这里要强调一下:时间复杂度都不带常数项或者常数系数,所以不存在所谓O(2n)这样的时间复杂度。
答案:D