算法及算法的評價


算法及算法的評價

算法

算法是對特定問題求解步驟的一種描述,它是指令的有點序列,其中每一條指令表示一個或多個操作。


算法的五個重要特性

有窮性、確定性、可行性、具有輸入、具有輸出。


好算法的特征

通常一個好的算法應該達到以下目標:

1.正確性:算法應當能正確地解決求解問題。

2.可讀性:算法應當具有良好的可讀性,以助人們理解。

3.健壯性:當輸入非法的數據時,算法也能適當的做出反應或進行處理,而不會產生莫名奇妙的輸出結果。

4.效率與低存儲量需求:效率是指算法的執行時間、存儲量需求是指算法執行過程中所需要的最大存儲空間,這兩者都與問題規模有關。


漸進分析:復雜度和大O記號的引入

回歸最初的問題,隨着問題的增長,計算成本應該如何增長?這里的我們只關心足夠大的問題規模,注重考察成本的增長趨勢。

漸進分析:在問題規模足夠大后,計算成本增長的分析。

時間復雜度和空間復雜度

是算法的效率的度量。

時間復雜度:一個語句的頻度是指該語句在算法中被重復執行的次數。算法中的所有語句的頻度之和記作\(T(n)\),它是該算法問題規模n的函數,時間復雜度主要分析\(T(n)\)的數量級,又因為算法中基本運算(最深層循環內的語句)的頻度與\(T(n)\)同數量級,所以通常采用算法中基本運算的頻度\(f(n)\)來分析算法的時間復雜度。因此,算法的時間復雜度記為:\(T(n) = O(f(n))\)

大O記號(big-O notation)

\(T(n) = O(f(n)) \quad\) \(iff \quad\) \(∃ \ c > 0\),當 \(n >> 2\)后,有\(T(n) < c*f(n)\)

\(\sqrt{5n*[3n*(n+2) + 4] + 6} < \sqrt{5n * [6n^2 + 4] + 6} < \sqrt{35n^3 + 6} < 6 * n^{1.5} = O(n^{1.5})\)

\(T(n)\)相比,\(f(n)\)更為簡潔,但依然反映着前者的增長趨勢。

常系數可忽略:\(O(f(n)) \ = \ O(c*f(n))\)

低次項可忽略:$O(n^a + n^b) = O(n^a) \(, 當\)a > b > 0$

時間復雜度:\(O(1)\)

常數(constant function)

\(2 = 2013 = 2013 * 2013 = O(1)\),甚至\(2013^{2013} = O(1)\) //含RAM各基本操作

這類算法效率最高(總不能奢望不勞而獲吧)

什么樣的代碼段對應於常數執行時間? (應具體分析)

一定不含循環?

for(i = 0; i < n; i += n / 2013 + 1);
for(i = 1; i < n; i = 1 << i)  // log*n,幾乎為常數

一定不含分支轉向?

if((n + m) * (n + m) < 4 * n * m) goto UNREACHABLE; //不考慮溢出

一定不能有(遞歸調用)?

if(2 == (n * n) % 5) O1(n);

時間復雜度:\(O(log^cn)\)

**對數\(log(n)\) **

\(lnn\)| $ lgn $| $log_{100}n $| \(log_{2013} n\)

**常底數無所謂 **

\({\forall}\ a,\ b > 0, \ log_an = \ log_ab * \ log_bn = \ Θ(log_bn)\)

**常數次冪無所謂 **

\({\forall}\ c \ > \ 0 ,\ logn^c \ = \ c * logn = Θ(logn)\)

**對數多項式(ploy-log function) **

\(123*log^{321}n \ + \ log^105(n^2 - n + 1) \ =\ Θ(log^{321}n)\)

這類算法非常有效,復雜度無限接近於常數:\({\forall} \ c \ > \ 0, \ logn \ = \ O(n^c)\)


時間復雜度:\(O(n^c)\)

**多項式(ploynomial function) : **

\(100n + 200 = O(n)\)

\((100n - 500)(20n^2 - 300n = 2013) \ = \ O(n * n^2) \ = \ O(n^3)\)

\((2013n^2 -20) / \ (1999n - 1) \ = \ O(n^2/n) \ = O(n)\)

一般地:\(a_kn^k + a_{k-1}n^{k-1} + ... + a_1n + a_0 \ = \ O(n^k), \ a_k > 0\)

線性(linear function):所有\(\ O(n)\)類函數

\(O(n)\)\(O(n^2)\):編程算法題的主要覆蓋范圍

冪:\([(n^{2013} -24n^{2009})^{1/3} + 512n^{567} - 1978n^{123}]^{1/11} \ = \ O(n^{61})\)


時間復雜度:\(O(2^n)\)

**指數(exponential function): **\(T(n) \ = \ a^n\)

\({\forall} \ c \ > \ 1,\ n^c \ = \ O(2^n)\)

\(n^{1000} \ = \ O(1.0000001^n) \ = \ O(2^n)\)

\(1.0000001^n = Ω(n^{1000})\)

這類算法的計算成本增長極快,通常被認為不可忍受。

\(O(n^c)\)\(O(2^n)\)是從有效算法到無效算法的分水嶺,很多問題\(O(2^n)\)的算法往往顯而易見,然后設計出\(O(n^c)\)的算法卻極其的不易,甚至,有時候注定是徒勞無功的,我們把這些問題分為NP和非NP問題。


復雜度層次


最壞時間復雜度:指在最壞的情況下,算法的時間復雜度。

平均時間復雜度:指所有輸入等可能的情況下,算法的期望運行時間。

最好時間復雜度:值在最好的情況下,算法的時間復雜度。

均攤時間復雜度:在代碼執行的所有復雜度情況中絕大部分是低級別的復雜度,個別情況是高級別復雜度且發生具有時序關系時,可以將個別高級別復雜度均攤到低級別復雜度上。基本上均攤結果就等於低級別復雜度。

舉例:有一個長度為n的數組,如果數組沒滿,就往里插入一個數,如果數組滿了,就遍歷求和.那么絕大多數情況下都是\(O(1)\),只有最后一次是\(O(n)\),均攤以后就是\(O(1)\)

復雜度振盪:數組等數據結構的擴容和縮容之間出現,原因是沒有處理好擴容和縮容因子之間的關系。


平均分析 VS 分攤分析

平均復雜度或期望復雜度(average/expected complexity)

根據數據結構各種操作出現概率的分布,將對應的成本加權平均。

各種可能的操作,作為獨立事件分別考察,割裂了操作之間的相關性連貫性,往往不能准確地評判數據結構和算法的真實性能。

分攤復雜度(amortized complexity)

對數據結構連續地實施足夠多次的操作,所需總體成本分攤至單次操作。

從實際可行的角度,對一系列操作做整體的考量,更加忠實地刻畫了可能出現的操作序列,可以更為精准地評判數據結構和算法的真實性能。


空間復雜度

算法的空間復雜度\(S(n)\),定義為該算法所耗費的輔助存儲空間,它是問題規模n的函數。漸進空間復雜度通常簡稱為空間復雜度,記作\(S(n) = O(g(n))\)

算法的 原地工作是指算法所需的輔助存儲空間是常量,即O(1)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM