1. 程式人生 > >資料結構與演算法之複雜度分析篇

資料結構與演算法之複雜度分析篇

一、內容

       最好情況時間複雜度、最壞情況時間複雜度、平均情況時間複雜度、均攤時間複雜度。

二、為什麼要引入這幾個概念?

       有助於我們可以更加全面地表示一段程式碼的執行效率,同樣一段程式碼,在不同的輸入情況下,複雜度量級有可能是不一樣的情況。

三、最好、最壞情況時間複雜度

        (1)、最好情況時間複雜度:在理想情況下,執行這段程式碼的時間複雜度;

        (2)、最壞情況時間複雜度:在最糟糕的情況下,執行這段程式碼的時間複雜度;

 舉例說明:

       最好情況時間複雜度:如果陣列中第一個元素正好是要查詢的變數X,那就不需要繼續遍歷剩下的n-1個數據了,那時間複雜度就是O(1);

       最壞情況時間複雜度:如果陣列中不存在變數X,那我們就需要把整個陣列都遍歷一遍,時間複雜度就成了O(n)。

四、平均情況時間複雜度

       引用上面的例子來說明,我們知道要查詢的變數X,要麼就不再數組裡。這兩種情況對應的概率統計起來很麻煩,為了方便你理解,我們假設在陣列中與不在陣列中的概率都為1/2。另外,要查詢的資料出現在0~n-1這n個位置的概率也是一樣的,為1/n。所以,根據乘法法則,要查詢的資料出現在0~n-1中任意位置的概率就是1/(2n)。

       因此,平均時間複雜度的計算過程就變成了這樣:

        這個值就是概率論中的加權平均值,也叫做期望值,所以平均時間複雜度的全稱應該叫加權平均時間複雜度或者期望時間複雜度。

       引入概率之後,前面那段程式碼的加權平均值為(3n+1)/4。用大O來表示,去掉係數和常量,這段程式碼的加權平均時間複雜度仍然是O(n)。

 五、均攤時間複雜度

        均攤時間複雜度,聽起來跟平均時間複雜度有點兒像。對於初學者來說,這兩個概念確實非常容易弄混。但大部分情況下,我們並不需要區分最好、最壞、平均三種複雜度。平均複雜度只在某些特殊情況下才會用到,而均攤時間複雜度應用的場景比它更加特殊、更加有限。

 (1)、應用場景:

     對一個數據結構進行一組連續操作中,大部分情況下時間複雜度都很低,只有在個別情況下時間複雜度比較高,而且這些操作之間存在前後連貫的時序關係,這個時候,我們就可以將這一組操作放在一塊兒分析,看是否能將較高時間複雜度那次操作的耗時,平攤到其他那些時間複雜度比較低的操作上。而且,在能夠應用均攤時間複雜度分析的場合,一般均攤時間複雜度就等於最好情況時間複雜度。

(2)、分析方法:攤還分析法;

舉例說明

       這段程式碼實現了一個往陣列中插入資料的功能。當陣列滿了之後,也就是程式碼中count==array.length時,我們用for迴圈遍歷陣列求和,並清空陣列,將求和之後的sum值放到陣列的第一個位置,然後再將新的資料插入陣列。

       由前面的知識可知,陣列中有空閒時間,我們只需將資料插入到陣列下標為count的位置就可以了,所以最好情況時間複雜度為O(1)。最壞的情況下,陣列中沒有空閒時間了,我們需要先做一次陣列的遍歷求和,然後再將資料插入,所以最壞情況時間複雜度為O(n)。

     對於平均時間複雜度,我們可以通過前面講的概率論的方法來分析。

     假設陣列的長度是n,根據插入的位置不同,我們可以分為n種情況,每種情況的時間複雜度是O(1)。除此之外,還有一種"額外"的情況,就是在陣列沒有空閒時間時插入一個數據,這個時候的時間複雜度是O(n)。而且,這n+1種情況發生的概率一樣,都是1/(n+1)。所以,根據加權平均的計算方法,我們求得的平均時間複雜度就是:

    

課後思考題:分析下面add()函式的時間複雜度。

       根據上面的所學的知識分析,我們可以得到:最好情況時間複雜度:O(1);最壞情況時間複雜度:O(n);均攤時間複雜度:O(1);   

       個人理解:對於add()函式,大部分情況下的時間複雜度為O(1);極端情況下的時間複雜度為O(n),平攤到時間複雜度為O(1)的操作上,最終平均時間複雜度為O(1);其實個人覺得當大部分情況下為O(1),那麼平均時間複雜度為O(1)。在能夠應用均攤時間複雜度分析的場合,一般均攤時間複雜度就等於最好情況時間複雜度。


歡迎大家掃碼關注微信公眾號,其中含有有大量免費的人工智慧、影象處理、IT資料:

                                                                            Change,There is no better way !