定義
如果存在正常數c與n0,使得當n >= n0時t(n) <= cf(n),則記為$t(n)= o(f(n))$。
如果存在正常數c與n0, 使得當n >= n0時t(n) >= cg(n),則記為$t(n) = \omega(g(n))$。
當且僅當t(n) = o(h(n))且t(n) = ω(h(n))時,則$t(n) = \theta(h(n))$。
如果t(n) = o(p(n))且t(n) != θ(p(n)),則$t(n) = o(p(n))$。
法則
如果t1(n) = $o(f(n))$且t2(n) = $o(g(n))$,那麼:
(a)t1(n) + t2(n) = $max(o(f(n)), o(g(n)))$
(b)t1(n) * t2(n) = $o(f(n) * g(n))$
如果t(n)是乙個k次多項式,則$t(n) = \theta(n^k)$
對於任意常數k,$\log^k = o(n)$
函式增長率
典型增長率
函式名稱c常數
$\log$
對數級$\log^2$
對數平方根
n線性級
$n\log$
$n^2$
平方級$n^3$
立方級$2^n$
指數級判斷兩個函式的增長率
可以通過比較兩個函式的極限:$\lim\limits_\frac$,來確定兩個函式的增長率。必要的時候,還可以使用洛必達法則。
該極限有4種可能:
1 極限是0,這意味著$f(n) = o(g(n))$;
2 極限是常數c != 0,這意味著$f(n) = \theta(g(n))$;
3 極限是$\infty$,這意味著$g(n) = o(f(n))$;
4 極限擺動,二者無關
for迴圈
一次for迴圈的執行時間至多是for迴圈內語句(包括測試)的執行時間乘以迭代得次數
for (i = 0; i < n; i++)}
上面的例子當中,時間複雜度是$n^2$。
順序語句
將各個語句的執行時間求和即可(這意味著,其中的最大值就是所得得執行時間)
for (i = 0; i < n; i++)for (i = 0; i < n; i++)
}
上面例子當中,第乙個迴圈時間複雜度是$o(n)$,第二個迴圈時間複雜度是$o(n^2)$,兩個迴圈的總體時間複雜度為$o(n) + o(n^2) = max(o(n), o(n^2))$,也就是還是$o(n^2)$。
if/else語句
對於程式片段:
if(condition)
else
乙個if/else語句得執行時間從不超過判斷再加上s1和s2中執行時間長的執行時間。
執行時間中的對數
如果乙個演算法用常數時間o(1)將問題的大小削減為其一部分(通常是1/2),那麼該演算法得時間複雜度就是$o(\log)$。舉個例子,下面是用迭代的方法寫的二分查詢:
int binarysearch(const elementtype a, elementtype x, intn)
else
else}}
return
notfound;
}
在上面的二分法中,每次迭代的時間複雜度是$o(1)$,並且每次迭代之後,問題複雜度就減為原來的一半,因此,這個程式的時間複雜度為$o(\log)$。
另一方面,如果使用常數時間只是把問題減少乙個常數(如將問題減少1),那麼這種演算法就是$o(n)$。舉個例子,下面使用遞迴的方式求解n!:
longint factorial(int
n)
else
}
在上面的遞迴中,每次遞迴的時間複雜度是$o(1)$,並且遞迴之後,問題複雜度只比原來少1,因此,這個程式的時間複雜度就是$o(n)$。
對於乙個問題複雜度為t(n)的問題,可以分解為如下的表示式:
$t(n) = at(\frac) + f(n)$,其中a是常數,且a >= 1, b也是常數,b > 1。
1 如果存在正常數$\varepsilon > 0$令$f(n) = o(n^ - \varepsilon})$,那麼$t(n) = \theta(n^})$;
2 如果$f(n) = \theta(n^^})$,那麼$t(n) = \theta(n^}\log)$;
3 如果存在正常數$\varepsilon > 0$使得$f(n) = \omega(n^} + \epsilon})$且存在常數c < 1使得對於足夠大的n滿足$af(\frac) \leq cf(n)$,那麼$t(n) = \theta(f(n))$.
這三種情形如何記憶呢?我們可以這樣記憶,三種情況的結果取決於函式f(n)與$n^^}$的大小。如果$n^^}$大,那麼結果就是情形1;如果是f(n)大,那麼結果就是情形3;如果兩個同級別,那麼就是情形2。
還需要注意的事情是,這三種情形沒有覆蓋所有的情形。情形1與情形2之間有gap,如果f(n)比$n^}$小,但是如果不是同時小乙個$n^\epsilon$因子,就落到情形1與情形2之間;同時,情形2與情形3之間也有gap,如果f(n)比$n^}$大,但是如果不同時大乙個$n^\epsilon$因子,就落到情形2與情形3之間。如果發生這兩種情形,就無法應用上面的三個公式。
下面我們看一下實際的例子。
1 $t(n) = 9t(\frac) + n$
其中a = 9, b = 3, f(n) = n,$n^ } = n^} = \theta(n^2)$,並且$f(n) = o(n^})$,其中$\varepsilon = 1$,那麼這個滿足情形1,即$t(n) = \theta(n^}) = \theta(n^2)$。
2 $t(n) = t(\fracn) + 1$
其中a = 1,b = $\frac$,f(n) = 1,同時$n^} = n^0 = 1$,那麼這就滿足情形2,即$t(n) = \theta(n^}\log) = \theta(\log)$。這其實就是上面執行時間中的對數當中得情形1。
3 $t(n) = 3t(\frac) + n\log$
其中a = 3,b = 4,f(n) = $n\log$,$n^} = n^} = \omega(n^)$。因為$f(n) = \omega(n^ + \varepsilon})$ $\varepsilon \cong 0.2$,同時對於足夠大的n,滿足$af(\frac) = 3(\frac)\log\frac \leq \fracn\log = cf(n)$,其中$c = \frac$。這就滿足了情形3,即$t(n) = \theta(n\log)$。
4 $t(n) = 2t(\frac) + n\log$
其中a = 2,b = 2,$f(n) = n\log$, $n^} = n^} = n$,表面上看,這屬於情形3,但是,卻不存在乙個正常數$\varepsilon$,使得$\frac + \varepsilon}} = \frac} + \varepsilon}} = \frac} = \frac} \ge 1$。所以無法運用上面3中情形的公式。
演算法分析基礎
1.級數 a.算數級數 等差 1 2 3 4 n o n 2 末項的平方 b.冪數級數 1 a 2 a n a o n a 1 末項的冪數加一次方 c.幾何級數 a 0 a 1 a 2 a n o a n 末項 d.調和級數 1 1 1 2 1 3 1 n o logn log1 log2 log3...
演算法分析基礎
定義 如果存在正常數c與n0,使得當n n0時t n cf n 則記為 t n o f n 如果存在正常數c與n0,使得當n n0時t n cg n 則記為 t n omega g n 當且僅當t n o h n 且t n h n 時,則 t n theta h n 如果t n o p n 且t n...
演算法和演算法分析基礎
演算法 對求解步驟的描述,是一組指令的有序序列,演算法必須是有窮的,可行的,並且要有輸入輸出 通常我們對演算法設計的要求有 正確性 應該滿足具體問題的需求。健壯性 經得起測試 效率與低儲存量 演算法執行的時間要越短越好,占用的儲存空間應該越少越好 演算法效率的度量 一般分為事後統計和事前分析估算 因...