演算法的時間複雜度

2021-07-10 22:48:23 字數 4266 閱讀 8490

演算法的時間複雜度是衡量乙個演算法效率的基本方法。在閱讀其他演算法教程書的時候,對於演算法的時間複雜度的講解不免有些生澀,難以理解。進而無法在實際應用中很好的對演算法進行衡量。

《大話資料結構》一書在一開始也針對演算法的時間複雜度進行了說明。這裡的講解就非常明確,言簡意賅,很容易理解。下面通過《大話資料結構》閱讀筆記的方式,通過原因該書的一些簡單的例子和說明來解釋一下演算法的時間複雜度和它的計算方法。

首先從基本定義下手,來了解一下什麼是「演算法的時間複雜度」,《大話資料結構》一書中對演算法的時間複雜度定義如下:

「演算法語句總的執行次數 t(n) 是關於問題規模 n 的函式,進而分析 t(n) 隨 n 的變化情況並確定 t(n) 的數量級。演算法的時間復                雜度,也就是演算法的時間度量,記作:t(n) = o(f(n)) 它表示隨問題規模 n 的增大,演算法執行時間的增長率和f(n) 的增長率                          相同,稱作演算法的漸進時間複雜度,簡稱為時間複雜度。其中 f(n) 是問題規模 n 的某個函式。」

光從定義來理解演算法的時間複雜度還是比較難的,我們再結合乙個簡單的例子來說明。計算 1 + 2 + 3 + 4 + ......  + 100 = ? 這樣的問題想必大家都遇到過,這裡我們通過 c 語言用最簡單的方法實現一下這個問題的演算法。

int sum = 0, n = 100;        //執行了 1 次

for (int i = 1; i <= n; i++)

printf(" sum = %d", sum);        //執行了 1 次

從**附加的注釋可以看到所有**都執行了多少次。那麼這寫**語句執行次數的總和就可以理解為是該演算法計算出結果所需要的時間。所以說,上述結算 1 + 2 + 3 + 4 + ......  + 100 = ?的演算法所用的時間(演算法語句執行的總次數)為 :

1 + ( n + 1 ) + n + 1 = 2n + 3

而當 n 不斷增大,比如我們這次所要計算的不是 1 + 2 + 3 + 4 + ......  + 100 = ? 而是 1 + 2 + 3 + 4 + ......  + n = ?其中 n 是乙個十分大的數字,那麼由此可見,上述演算法的執行總次數(所需時間)會隨著 n 的增大而增加,但是在 for 迴圈以外的語句並不受 n  的規模影響(永遠都只執行一次)。所以我們可以將上述演算法的執行總次數簡單的記做:

2n 或者簡記  n

這樣我們就得到了我們設計的計算 1 + 2 + 3 + 4 + ......  + 100 = ?的演算法的時間複雜度,我們把它記作:

o(n)

對於同乙個問題,解法通常是不唯一的。比如 1 + 2 + 3 + 4 + ......  + 100 = ?這個問題,還有其他的不少演算法。我們再來看乙個數學家高斯解決這個問題的演算法(想必大家都很熟悉這個故事)。

sum = 1 + 2 + 3 + 4 + ......  + 100

sum = 100 + 99 + 98 + 97 + ...... + 1

sum + sum = 2*sum = 101 + 101 + 101 + .... + 101          正好 100 個 101

sum =  (100*101)/2 = 5050

同樣我們將這個解法翻譯成 c 語言**:

int n = 100, sum = 0;        //執行 1 次

sum = (n*(n + 1))/2;        //執行 1 次

printf("sum = %d", sum);        //執行 1 次

這樣我們針對同乙個 1 + 2 + 3 + 4 + ......  + 100 = ?問題,不同的演算法又的到了乙個演算法的時間複雜度:

o(3)    一般記作 o(1) 我們後續給出原因。

從感官上我們就不難看出,從演算法的效率上看,o(3) < o(n) 的,所以高斯的演算法更快,更優秀(是最優秀的嗎?)。

這種用個大寫的 o 來代表演算法的時間複雜度的記法有個專業的名字叫「大o階」記法。那麼通過對上述的例子進行總結,我們給出演算法的時間複雜度(大o階)的計算方法。

推導「大o階」的步驟:

1、用常數 1 取代執行時間中的所有加法常數。

2、在修改後的執行次數函式中,只保留最高端項。

3、如果最高端項存在且不是 1 ,則去除與這個項相乘的常數。

下面我們在通過乙個有不少 for 迴圈的例子按照上面給出的推導「大o階」的方法來計算一下演算法的時間複雜度。先看一下下面的這個例子的**,也是用 c 語言寫的,在注釋上我們仍然對執行次數進行說明。

int n = 100000;        //執行了 1 次

for (int i = 0; i < n; i++)

}for (int i = 0; i < n; i++)

printf("done");        //執行了 1 次

上面的**嚴格的說不能稱之為乙個演算法,畢竟它很「無聊而且莫名其妙」(畢竟演算法是為了解決問題而設計的嘛),先不論這個「演算法」能解決什麼問題,我們看一下它的「大o階」如何推導,還是先計算一下它的執行總次數:

執行總次數 = 1 + (n + 1) + n*(n + 1) + n*n + (n + 1) + 1 = 2n^2 + 3n + 3    這裡 n^2 表示 n 的 2次方。

按照上面推導「大o階」的步驟我們先來第一步:「用常數 1 取代執行時間中的所有加法常數」,則上面的算式變為:

執行總次數 = 2n^2 + 3n + 1    這裡 n^2 表示 n 的2次方

第二步:「在修改後的執行次數函式中,只保留最高端項」。這裡的最高端是 n 的二次方,所以算式變為:

執行總次數 = 2n^2    這裡 n^2 表示 n 的2次方

第三步:「如果最高端項存在且不是 1 ,則去除與這個項相乘的常數」。這裡 n 的二次方不是 1 所以要去除這個項的相乘常數,算式變為:

執行總次數 = n^2    這裡 n^2 表示 n 的2次方

因此最後我們得到上面那段**的演算法時間複雜度表示為: o( n^2 )        這裡 n^2 表示 n 的2次方。

至此,我們對什麼是「演算法的時間複雜度」和「演算法的時間複雜度」表示法「大o階」的推導方法進行了簡單的說明。當然要想在日後的實際工作中快速準確的推導出各種演算法的「大o階」我們還需要進行大量的聯絡,畢竟熟能生巧嘛。最後我們在把常見的演算法時間複雜度以及他們在效率上的高低順序記錄在這裡,是大家對演算法的效率有個直觀的認識。

o(1) 常數階 < o(logn) 對數階 < o(n) 線性階 < o(nlogn) < o(n^2) 平方階 < o(n^3) <  

最後三項我用大括號把他們括起來是想要告訴大家。如果日後大家設計的演算法推導出的「大o階」是大括號中的這幾位,那麼趁早放棄這個演算法,在去研究新的演算法出來吧。因為大括號中的這幾位即便是在 n 的規模比較小的情況下仍然要耗費大量的時間,演算法的時間複雜度大的離譜,基本上就是「不可用狀態」。

當然了,還是要推薦一下《大話資料結構》這本書的。對於資料結構入門來說,這本書相當不錯,很「生動活潑」,讀起來也很有意思!

乙個演算法如果能在每個步驟去掉一半資料元素,如二分檢索,通常它就取 o(logn)時間。

若演算法的 t(n) =o(log n),則稱其具有對數時間。由於計算機使用二進位制

的記數系統,對數

常常以10為底(即log10n,有時寫作 lg n)。然而,由對數的換底公式

,logan和 logb n只有乙個常數因子不同,這個因子在大o記法中被丟棄。因此記作o(log n),而不論對數的底是多少,是對數時間演算法的標準記法

o(nlogn)是比較排序演算法的下限,

所以如果你是靠每次比較兩個元素來排序那麼沒有更快的了,

首先,所有基於比較的排序演算法,都是以決策樹模型作為依據的。

n 個元素,其所有可能的排序種數為 n! ,其決策樹 高度 為 h (即為排序演算法比較的次數)

高度為 h 的決策樹,最多有 葉子節點

由斯特林近似公式:

得其中,

故,不基於比較的排序演算法就不受這個限制,例如桶排序。

其實大部分時候說的複雜度就是直觀上的複雜度,看看他與哪些因素成比例,並去掉影響不大的項。

像堆結構一般來說就是均攤logn的,分析複雜度很多時候是很複雜的,需要用到很多數學知識,特別是概率演算法,均攤分析。

不過記住 常用結構的複雜度,很多時候複雜度就是用常用結構組合起來用的,所以大致複雜度就能知道了(如乘起來或加起來)

演算法時間複雜度空間複雜度

演算法 是解決某一類問題的通法,即一系列清晰無歧義的計算指令。每個演算法只能解決具有特定特徵的一類問題,但乙個問題可由多個演算法解決。乙個演算法應該有以下五個方面的特性 比較演算法的優劣我們從兩個維度去進行考量 時間 空間 時間複雜度,空間複雜度 找出基本語句 演算法中執行次數最多的那條語句就是基本...

演算法 時間複雜度 空間複雜度

1 if i 1 2 a 1 result 3 4 result n 2 result 1000 1000 3 array.push a array.pop 4 map.set 1,1 map.get 1,1 在計算複雜度的時候,o 1 一般會被忽略。1 for let i 0 i n i 2 wh...

演算法的時間複雜度 空間複雜度

時間複雜度和空間複雜度是度量演算法效率的常用指標 事後統計,不常用 事前統計影響因素 演算法策略 問題規模 程式語言 質量 機器執行指令的速度 撇開軟硬體的影響,演算法執行工作量的大小只依賴於問題的規模 通常用整數n表示 乙個演算法是由控制結構 順序,分支,迴圈三種 和原操作 指固有資料型別的操作 ...