代碼千千萬,有些代碼邏輯會很複雜,因此爲了更細化的分析算法的複雜度,再複雜度分析方面引入了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)。
應用場景:均攤時間複雜度和攤還分析應用場景較爲特殊,對一個數據進行連續操做,大部分狀況下時間複雜度都很低,只有個別狀況下時間複雜度較高。而這組操做其存在先後連貫的時序關係。
這個時候咱們將這一組操做放在一塊兒分析,將高複雜度均攤到其他低複雜度上,因此通常均攤時間複雜度就等於最好狀況時間複雜度。
注意:均攤時間複雜度是一種特殊的平均複雜度(特殊應用場景下使用),掌握分析方式便可。