算法时间复杂度计算

2022.5.12

计算算法时间复杂度

  • 分析
  • 一、简单循环及其变种
  • 二、层层影响循环
  • 总结


分析

算法中所有语句的频度之和记为T(n),它是该算法问题规模n的函数。
对于一个算法来说,循环体和递归是时间复杂度的重灾区,在这里先分析循环体的时间复杂度。

预备知识:
1.常见渐进时间复杂度

O(1)2)3)n)n)

2.计算时间复杂度时,系数可省略,O记法只看加项的最高阶

一、简单循环及其变种

[例1]
void fun(int n)
{
int i=1;         //语句频度1,后期可以忽略
while(i<=n)      //i<=n是循环条件
i=i*2;           //i=i*2控制循环次数
}

这里我们计算时间复杂度需要计算的就是循环体的语句频度。
设循环次数:t
根据循环体可得:2t<=n,此时循环可以继续下去
接下来只需求解出:t<=log2n,即可得到T(n)=O(log2n)
此时的t对应的就是语句的频度。

[例2]
void fun(int n)
{
int i=1;             //语句频度1,后期可以忽略
while(i*i*i<=n)      //i*i*i<=n是循环条件
i++;                 //i++和i*i*i控制循环次数
}

这里我们依旧计算循环体的语句频度。
设循环次数:t
根据循环体可得:t=i,t3<=n,此时循环可以继续下去
接下来只需求解出:t<=3√n ,即可得到T(n)=O(3√n)
此时的t对应的就是语句的频度。

[例3]
void fun(int n)
{
int x=2;             //语句频度1,后期可以忽略
while(x<n/2)         //x
x=2*x;               //x=2*x和n/2控制循环次数
}

这里我们依旧计算循环体的语句频度。
设循环次数:t
根据循环体可得:2t+1 接下来只需求解出:t2n-2 ,即可得到T(n)=O(log2n)
此时的t对应的就是语句的频度。

[例4]
void fun(int n)
{
int x=0;                      //语句频度1,后期可以忽略
while(n>=(x+1)*(x+1))         //n>=(x+1)*(x+1)是循环条件
x=x+1;                        //x=x+1和(x+1)*(x+1)控制循环次数
}

这里我们依旧计算循环体的语句频度。
设循环次数:t
根据循环体可得:(t+1)2<=n,此时循环可以继续下去
接下来只需求解出:t<=√n-1 ,即可得到T(n)=O(√n)
此时的t对应的就是语句的频度。

[例5]
void fun(int n)
{
int count=0;                   //语句频度1,后期可以忽略
for(k=1;k<=n;k*=2)             //k<=n是循环条件
for(j=1;j<=n;j++)              //j<=n是循环条件
count++;                       //k*=2和j++控制循环次数
}

这里我们依旧计算循环体的语句频度。
设循环次数:t1和t2
根据循环体可得:2t1<=n且t2<=n,此时循环可以继续下去
接下来只需求解出:t1<=log2n和t2<=n ,总循环次数t=t1xt2,即可得到T(n)=O(nlog2n)
此时的t对应的就是语句的频度。

二、层层影响循环

[例6]
void fun(int n)
{
for(i=n-1;i>1;i--)             //i>1是循环条件
for(j=1;j<i;j++)               //j
if(A[j]>A[j+1];                //i--和j++控制循环次数
A[j]与A[j+1]互换;
}

这里的循环体是多层嵌套且相互关联的,所以在计算时要采用其它方式。
由循环体可以列出:
T ( n ) = ∑ i = 2 n − 1 ∑ j = 1 i − 1 1 = ( n − 1 ) ( n − 2 ) 2 T(n)=∑_{i=2}^{n-1} ∑_{j=1}^{i-1}1 =\displaystyle { \frac{(n-1)(n-2)}{2} } T(n)=i=2n1j=1i11=2(n1)(n2)
直接得到T(n)=O(n2)

[例7]
void fun(int n)
{
int m=0,i,j;                 //语句频度1,后期可以忽略
for(i=1;i<=n;i++)            //i<=n是循环条件
for(j=1;j<=2*i;j++)          //j<=2*i是循环条件
m++;                         //2*i和i++和j++控制循环次数
}

由循环体可以列出:
T ( n ) = ∑ i = 1 n ∑ j = 1 2 i 1 = ( 2 n + 2 ) n 2 T(n)=∑_{i=1}^{n } ∑_{j=1}^{2i}1 =\displaystyle { \frac{(2n+2)n}{2} } T(n)=i=1nj=12i1=2(2n+2)n
直接得到T(n)=O(n2)

[例8]
void fun(int n)
{
int m=0;
for(i=1;k<=n;i++)          //k<=n是循环条件
for(j=1;j<=i;j++)          //j<=i是循环条件
for(k=1;k<=j;k++)          //k<=j是循环条件
m++;                       //k++和i++和j++控制循环次数
}

由循环体可以列出:
T ( n ) = ∑ i = 1 n ∑ j = 1 i ∑ k = 1 j 1 = [ ( n + 1 ) n 2 + 1 ] ∗ n / 2 T(n)=∑_{i=1}^{n } ∑_{j=1}^{i}∑_{k=1}^{j}1 =[\displaystyle { \frac{(n+1)n}{2} +1]*n/2} T(n)=i=1nj=1ik=1j1=[2(n+1)n+1]n/2
直接得到T(n)=O(n3)


总结

所有题目来自王道书。
可以对比例5和后面几个多层循环,当不同的层互不影响时,就能够将不同层分开计算。

你可能感兴趣的:(学习,算法,数据结构)