算法复杂度分析(下):最好、最坏、平均、均摊等时间复杂度概述

细化时间复杂度分析

代码千千万,有些代码逻辑会很复杂,因此为了更细化的分析算法的复杂度,再复杂度分析方面引入了4个知识点:算法

1.最好状况时间复杂度(best case time complexity)。spa

2.最坏状况时间复杂度(worst case time complexity)。code

3.平均状况时间复杂度(average case time complexity)。blog

4.均摊时间复杂度(amortized time complexity)。it

 

复杂度分析 

示例以下(限定条件:0<n且0<x且n和x为整数):io

 1 public int Function(int n, int x)
 2  {
 3      int sum = 0;
 4      for (int i = 1; i <= n; ++i)
 5      {
 6          if (i == x)
 7              break;
 8          sum += i;
 9      }
10      return sum;
11  }
12  /*
13  * 做者:Jonins
14  * 出处:http://www.cnblogs.com/jonins/
15  */

这段代码逻辑很是简单,再此不描述。须要重点分析的是循环这一段代码,这段代码根据x值的不一样,时间复杂度也有区别:class

1.当x>n时,此代码的时间复杂度是O(n)基础

2.当1<=x<=n时,时间复杂度是一个咱们不肯定的值,取决于x的值。循环

3.当x=1时,时间复杂度是O(1)遍历

这段代码在不一样状况下,其时间复杂度是不同的。因此为了描述代码在不一样状况下的不一样时间复杂度,咱们引入了最好最坏平均时间复杂度

 

最好状况时间复杂度

最好状况时间复杂度,表示在最理想的状况下,执行这段代码的时间复杂度。

上述示例就是当x=1的时候,循环的第一个判断就跳出,这个时候对应的时间复杂度就是最好状况时间复杂度。

 

最坏状况时间复杂度

最坏状况时间复杂度,表示在最糟糕的状况下,执行这段代码的时间复杂度。

上述示例就是n<x的时候,咱们要把整个循环执行一遍,这个时候对应的时间复杂度就是最坏状况时间复杂度。

 

平均状况时间复杂度

最好和最好状况是极端状况,发生的几率并不大。为了更有效的表示平均状况下的时间复杂度,引入另外一个概念:平均状况时间复杂度

分析上面的示例代码,判断x在循环中出现的位置,有n+1种状况:1<=x<=n 和n<x

咱们将全部状况下代码执行的次数累加起来1+2+3....+n)+n,而后再除以全部状况数量(n+1),就能够获得须要遍历次数的平均值。

平均状况复杂度为:

$ \frac{((1+2+3...+n)+n)}{(n+1)}=\frac{n(n+3)}{2(n+1)} $

推导过程:

$ \because 1+2+3...+n=n+(n-1)+(n-2)...+1 $

$ \therefore (1+2+3...+n)=\frac{n(1+n)}{2} $

$ \therefore   (1+2+3...+n)+n= \frac{n(3+n)}{2} $

大O表示法,会省略系数、低阶、常量,因此平均状况时间复杂度是O(n)

可是这个平均复杂度没有考虑各自状况的发生几率,这里的n+1状况,它们的发生几率是不同的,因此还须要引入各自状况发生的几率再具体分析。

x要么在1~n中,要么不在1~n中,因此它们的几率都是$\frac{1}{2}$

同时数据在1~n中各个位置的几率都是同样的为$\frac{1}{n}$。根据几率乘法法则,x在1~n中任意位置的几率是$\frac{1}{2n}$

所以在前面推导过程的基础上,咱们把每种状况发生的几率考虑进去,那么平均状况时间复杂度的计算过程变成:

考虑几率的平均状况复杂度为:

$(1\frac{1}{2n}+2\frac{1}{2n}+3\frac{1}{2n}...+n\frac{1}{2n})+n\frac{1}{2}=\frac{3n+1}{4}$

推导过程:

$\because (1+2+3...+n)=\frac{n(1+n)}{2}$ 

$\therefore (1\frac{1}{2n}+2\frac{1}{2n}+3\frac{1}{2n}...+n\frac{1}{2n})=\frac{1}{2n}(1+2+3...+n)=\frac{1}{2n}*\frac{n(1+n)}{2} =\frac{1+n}{4}$ 

$\therefore (1\frac{1}{2n}+2\frac{1}{2n}+3\frac{1}{2n}...+n\frac{1}{2n})+n\frac{1}{2}=\frac{1+n}{4} +n\frac{1}{2}=\frac{3n+1}{4}$ 

 

这就是几率论中的加权平均值,也叫作指望值,因此平均时间复杂度全称叫:加权平均时间复杂度或者指望时间复杂度

引入几率以后,平均复杂度变为O($\frac{3n+1}{4}$),忽略系数及常量后,最终获得加权平均时间复杂度为O(n)。

注意:

多数状况下,咱们不须要区分最好、最坏、平均状况时间复杂度。只有同一块代码在不一样状况下时间复杂度有量级差距,咱们才会区分3种状况,为的是更有效的描述代码的时间复杂度。

 

均摊状况时间复杂度

均摊复杂度是一个更加高级的概念,它是一种特殊的状况,应用的场景也更加特殊和有限。

对应的分析方式称为:摊还分析或平摊分析。

示例以下(限定条件:0<=x<=n且0<=n且n,x为整数):

 1 int n;
 2 int Function2(int x)
 3 {
 4     int count = 0;
 5     if (n == x)
 6     {
 7         for (int i = 0; i < n; i++)
 8         {
 9             count += i;
10         }
11     }
12     else
13         count = x;
14     return count;
15 }
16 /* 做者:Jonins
17 * 出处:http://www.cnblogs.com/jonins/
18 */

分析上述案例的时间复杂度:

最理想状况下x!=n,只执行一次赋值便可推出,因此最好时间复杂度为O(1)。

最坏的状况下x=n,要执行一次循环累加和的操做,因此最好时间复杂度为O(n)。

平均的状况下,由于限定条件0<=x<=n,x在0~n中存在的位置能够分为n+1种状况(0到n)。

0<=x<n时,时间复杂度为O(1)。可是x=n的时候是一个例外,它的复杂度是O(n)。

并且这n+1种状况发生的几率都是同样的,为$\frac{1}{n+1}$。因此根据加权平均的计算方法,

平均时间复杂度为:

$ (1\tfrac{1}{n+1}+1\tfrac{1}{n+1}+1\tfrac{1}{n+1}+...+1\tfrac{1}{n+1})+n\tfrac{1}{n+1} = \tfrac{2n}{n+1} $

推导过程:

$(1\tfrac{1}{n+1}+1\tfrac{1}{n+1}+1\tfrac{1}{n+1}+...+1\tfrac{1}{n+1})+n\tfrac{1}{n+1}$

$=n\tfrac{1}{n+1}+n\tfrac{1}{n+1}$

$=\tfrac{2n}{n+1}$

当省略系数及常量后,平均时间复杂度为O(1)。

摊还分析法

分析上述示例的平均复杂度分析并不须要如此复杂,无需引入几率论的知识。

由于经过分析能够看出,上述示例代码复杂度大多数为O(1),极端状况下复杂度才较高为O(n)。同时复杂度遵循必定的规律,通常为1个O(n),和n个O(1)。针对这样一种特殊场景使用更简单的分析方法:摊还分析法

经过摊还分析法获得的时间复杂度为均摊时间复杂度

大体思路:每一次O(n)都会跟着n次O(1),因此把耗时多的复杂度均摊到耗时低的复杂度。获得的均摊时间复杂度为O(1)。

应用场景:均摊时间复杂度和摊还分析应用场景较为特殊,对一个数据进行连续操做,大部分状况下时间复杂度都很低,只有个别状况下时间复杂度较高。而这组操做其存在先后连贯的时序关系。

这个时候咱们将这一组操做放在一块儿分析,将高复杂度均摊到其他低复杂度上,因此通常均摊时间复杂度就等于最好状况时间复杂度。

注意:均摊时间复杂度是一种特殊的平均复杂度(特殊应用场景下使用),掌握分析方式便可。

相关文章
相关标签/搜索