複雜度分析

1 爲何要對算法進行復雜度分析?node

數據結構與算法就是爲了解決如何更省的存儲數據、如何更快的處理數據的問題,那麼就必須有一個準則對「更快」、「更省」進行判斷。算法

ok,能夠,既然我們要分析算法的執行時間和運行時佔用的內存,那好辦呀,我們就在Visual Studio上把代碼跑一遍就能夠了。數據結構

                                                            

這種測試方法固然是對的,可是對於算法的複雜度分析來講,卻有兩個缺陷:一是這種測試方法對測試環境依賴很嚴重,例如同一段代碼在i3和i9上運行,i9上跑的i3快;二是輸入數據的不肯定性,輸入數據的規模和有序度都會影響算法的執行時間。測試

因此纔有了空間、時間複雜度分析。spa

 

2 什麼是時間複雜度、空間複雜度?code

2.1 時間複雜度:測試運行時間就是計算對運行時間有消耗的基本操做的執行次數,那麼咱們能夠假設一個前提,每一行代碼執行的時間(baseTime)是同樣的。例如,blog

 1 long add(int n)
 2 {
 3     int i = 1;
 4     int j = 1;
 5     long sum = 0;
 6     
 7     for ( , i < n, ++i)
 8     {
 9         for (, j < n, ++j)
10             sum += i*j;
11     }
12 
13     return sum;
14 }

外層循環每執行一次,內層循環執行n次,因此咱們知道總共執行次數f(n) = 2n2+n+4,總共執行時間T(n) = f(n) * baseTime,也能夠表示成T(n) = O(f(n)),‘O’表示總執行時間和執行語句數量f(n)成正比,叫作大O複雜度表示法。遞歸

大O複雜度並不具體表示代碼真正的執行時間,而是代碼執行時間隨數據輸入規模增加的變化趨勢。記錄時咱們只需關注最大量級便可,上述例子就可表示成O(n2)。內存

2.3 時間複雜度分析技巧rem

1) 只要算法中不存在循環語句、遞歸語句,即便有成千上萬行的代碼,其時間複雜度也是O(1);

2) 只關注循環次數最多的一段代碼;

3) 加法原則:總複雜度等於量級最大的那段代碼的複雜度;

4) 乘法原則:嵌套代碼的複雜度等於嵌套內外代碼複雜度的乘積。

2.4 常見的時間複雜度

O(1) < O(logn) < O(n) < O(nlogn) < O(n2) < O(n3) < O(2n) < O(n!) < O(nn)

2.5 空間複雜度

與時間複雜度相似,空間複雜度表示的是代碼執行過程當中所需存儲空間隨數據輸入規模增加的變化趨勢,一樣能夠用大O表示法表示。這裏所需的存儲空間是說除了輸入數據存儲空間外,算法運行還需額外的存儲空間。 

 1 ListNode* removeNthFromEnd(ListNode* head, int n) {
 2     vector<ListNode*> nodeVector;    //建立一個節點容器
 3     ListNode* pWorkNode = head;
 4     int i = 0;    //鏈表長度
 5         
 6     while (pWorkNode)    //遍歷鏈表
 7     {
 8         nodeVector.push_back(pWorkNode);    //將各個節點放入容器中
 9         pWorkNode = pWorkNode->next;
10         ++i;
11     }
12         
13     int j = i + 1 - n;    //待刪除節點序號
14     if (1 == j)    //若是刪除的是第一個節點
15     {
16         pWorkNode = head->next;
17         delete head;
18         head = pWorkNode;
19     }
20     else
21     {
22         nodeVector[j - 2]->next = nodeVector[j - 1]->next;
23         delete nodeVector[j - 1];
24     }
25         
26     return head;
27 }

該例子中在運行過程當中建立了一個長度爲n的容器,空間複雜度爲O(n)。

 

3 最好狀況時間複雜度、最壞狀況時間複雜度和平均狀況時間複雜度

1) 最好狀況時間複雜度:最理想的狀況下,執行這段代碼的時間複雜度。

2) 最壞狀況時間複雜度:最糟糕的狀況下,執行這段代碼的時間複雜度。

3) 平均狀況時間複雜度:平均狀況下的時間複雜度。

通常只有在同一塊代碼在不一樣的狀況下,時間複雜度有量級的差距,纔會使用這三種複雜度表示法來區分。

 

4 均攤時間複雜度

攤還分析法:將特殊耗時多的那次或幾回操做均攤到剩下的n次耗時少的操做上。大多數狀況下,均攤時間複雜度都等於最好狀況複雜度。

適用場景:對一個數據結構進行一組連續操做中,大部分狀況下時間複雜度都很低,只有個別狀況下時間複雜度比較高,並且這些操做之間存在先後連貫的時序關係,這個時候,咱們就能夠將這一組操做放在一塊兒分析,看是否能將較高時間複雜度的那次操做的耗時,平攤到其餘那些時間複雜度比較低的操做上。

相關文章
相關標籤/搜索