演算法時間複雜度分析(1)
如果有錯誤的地方,歡迎大家指正,只希望不要誤導別人。
開篇:
學習演算法時間複雜度分析,首先要對O、o、Ω、ω、Θ這幾個符號有基本的瞭解,下面將給出這幾個符號詳細的定義。
1、大O符號:
定義:
設f和g是定義域為自然數集N上的函式,若存在正數c和n0,,使得對一切 n >= n0有 0 <= f(n) <= cg(n)成立, 則
稱f(n)的漸進上界是g(n),記做:f(n) = O(g(n))
例子:
f(n) = n^2 + n, g(n) = n^2; 當 c = 2, 只要n0 = 1, 就滿足, f(n) <= cg(n) ==> 這個時候稱g(n)為f(n)的漸進上界,
記作:f(n) = O(n^2)
注意:
1、f(n) = O(g(n)),f(n)的階不高於g(n)的階。
2、可能存在多個正數c,只要指出一個即可。
3、對前面有限個值可以不滿足不等式。
4、常函式可以寫作O(1).
2、小o符號:
定義:
設f和g是定義域為自然數集N上的函式,若對於任意正數c都存在n0,使得對一切 n >= n0,有 0 <= f(n) < cg(n)成立,
則記作f(n) = o(g(n))
例子:
f(n) = n^2 + n , 則f(n) = o(n^3) c >= 1成立,因為n^2 + n < cn^3(n0 = 2)
任給1 > c > 0, 取n0 > ⌈2/c⌉即可,因為
cn >= cn0 > 2 (當 n >= n0)
n^2 + n < 2n^2 < cn^3
注意:
1、f(n) = o(g(n)),f(n)的階低於g(n)的階。
2、對不同正數c,n0不一樣,c越小n0越大。
3、對於前面有限個n值可以不滿足不等式。
3、大Ω符號:
定義:
設f和g是定義域為自然數集N上的函式,若存在正數c和n0,使得 對一切 n >= n0, 0 <= cg(n) <= f(n),成立,
則稱f(n)的漸進下界是g(n),記作f(n) = Ω(g(n));
例子:
f(n) = n^2 + n, g(n) = n^2
當c = 1時,只要n0 = 1 就滿足,cg(n) <= f(n) ==> 這個時候稱g(n)為f(n)的漸進下界,記作:f(n) = Ω(n^2)
注意:
1、f(n) = Ω(g(n)),f(n)的階不低於g(n)的階。
2、可能存在多個正數c,指出一個即可。
3、對前面有限個n值可以不滿足上述不等式。
4、小ω符號:
定義:
設f和g是定義域為自然數集N上的函式,若對於任意正數c都存在n0,使得對於一切n >= n0,
有 0 <= cg(n) < f(n) 成立,則記作f(n) = ω(g(n)).
例子:
設f(n) = n^2 + n,則 f(n) = ω(n),不能寫f(n) = ω(n^2),因為c =2,不存在n0使得一切n > n0有下式成立
cn^2 = 2n^2 < n^2 + n
注意:
1、f(n) = ω(g(n)),f(n)的階高於g(n)的階。
2、對不同的正數c,n0不等,c越大n0越大。
3、對前面有限個n值可以不滿足不等式。
5、Θ符號:
定義:
若f(n) = O(g(n)) 且 f(n) = Ω(g(n)),則記作:f(n) = Ω(g(n))
例子:
f(n) = n^2 + n. g(n) = 100n^2,那麼有f(n) = Θ(g(n))
注意:
1、f(n)的階與g(n)的階相等
2、對前面有限個n值可以不滿足條件
漸進:
經過上面的介紹,想必大家對這幾個符號的定義有了基本的瞭解。那麼,現在我們再來了解一下幾個常用的定理。
1、定理1:
(1)如果n -> ∞,f(n) / g(n) 存在,並且等於某個常數 c > 0,那麼, f(n) = Θ(g(n))
(2) 如果n -> ∞,f(n) / g(n) = 0, 那麼, f(n) = o(g(n))
(3) 如果n -> ∞,f(n) / g(n) = +∞,那麼, f(n) = ω(g(n))
2、定理2:
設函式f, g, h的定義域為自然數集合
(1) 如果 f = O(g) 且 g = O(h), 那麼 f = O(h)
(2) 如果 f = Ω(g) 且 g = Ω(h),那麼 f = Ω(h)
(3) 如果 f = Θ(g) 和 g = Θ(h), 那麼 f = Θ(h)
3、定理3:
假設函式 f 和 g 的定義域為自然數集,若對某個其它函式h,有f = O(h) 和 g = O(h), 那麼 f + g = O(h)
ps:該性質可以推廣到有限個函式。演算法由有限步驟構成。若每一步的時間複雜度函式的上界都是h(n),那麼該演算法的時間
複雜度可以寫作O(h(n))
入門:
上面介紹了演算法領域常見的幾個漸進符號。這裡重點再介紹一下大O符號。大O符號常被用在表示演算法時間複雜度。 這裡
需要理清一些概念,首先,大O表示的是某個函式的漸進上界,在上面的定義中可以知道, 0 <= f(n) <= cg(n),這裡g(n)的階
是可以高於f(n)的,所以,O(g(n))並不明確用來表示,最壞時間複雜度或平均時間複雜度,所以,通常你能看見的說法都是,
最壞時間複雜度O(g(n)),和平均複雜度O(g(n))。那麼,有沒有專門用來表示最壞時間複雜度的符號和表示平均時間複雜度的
符號?有,通常用W(g(n))表示最壞的時間複雜度,A(g(n))表示平均的時間複雜度。
(1) 問題1:如何衡量演算法的時間複雜度?
一個演算法的執行時間,去掉不定因素(比如:計算機的運算能力等),演算法的執行時間其實是受演算法的輸入和
演算法本身的設計好壞所影響的。所以,我們衡量一個演算法的執行時間,可以通過基本運算的執行次數來衡量。通常
用T(n)表示基本運算的執行次數。而什麼叫基本運算?加、減、乘、除、比較等都是基本的運算。比如:一個基於
比較的排序演算法,那麼這個演算法的基本運算就是比較,我們只要統計出這個基本運算的執行次數就能估算出演算法的
時間複雜度。
(2) 問題2: 漸進時間複雜度?
通過上一個問題的介紹,我們可以知道,一個演算法的執行效率,其實是可以通過基本語句的執行次數來衡量。但
是,這樣的方式估算演算法複雜度太過麻煩,所以引入了漸進時間複雜度。漸進時間複雜度的好處在於,可以忽略低階
項和最高階項係數,這樣估算時間複雜度會快速許多。
(3) 問題3: 常數時間?
通常常數時間用O(1)表示,那麼,什麼情況下可以認為是常數時間?主要有兩個情況。
1、當該執行語句與輸入n無關時,可以認為該語句的執行時間為常數時間。
2、當該執行語句在 t 時間內能夠執行完,也可以認為是常數時間。
簡單例子:
現在舉幾個簡單的時間複雜度分析的例子。首先看下面一段程式碼。
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
count++;
}
}
首先:n代表的是輸入規模,其中基本操作語句是自加,那麼count++執行了多少次?我們假設輸入規模 n = 10,那麼count
的執行次數是 (10 + 1)*10/2 = 55。所以,T(n) = (n + 1)*10/2 = 1/2*n^2 + 1/2*n,當f,g在定義域為自然數N上的函式,當存在一
個整數c和n0,使得 n >= n0時,0 <= f(n) <= cg(n),記作:f(n) = O(g(n)),g(n)稱為f(n)的漸進上界,這裡的T(n)就是f(n),當c = 2,
n0 = 1, f(n) = 1/2*n^2 + 1/2*n <= cg(n) = 2*n^2 ==> 所以:f(n) = O(n^2)。
對於上面的例子,最壞和平均複雜度都是O(n^2),因為該演算法只與輸入規模n有關。
其實,多重迴圈中,如果每層迴圈都與輸入規模有關的話,那有幾層迴圈,時間複雜度就是n的幾次方。
現在再來看看另外一個例子:
public int binarySearch(int[] arr, int l, int r, int target) {
if(l > r)
return -1;
int mid = (l + r) / 2;
if(arr[mid] == target)
return mid;
if(target < arr[mid])
return binarySearch(arr, l, mid -1, target);
else
return binarySearch(arr, mid + 1, r, target);
}
上面是一個簡單的二分搜尋。搜尋過程,其實就是比較的過程,所以上述演算法的基本運算就是比較。
現在我們試著分析一下二分搜尋的平均時間複雜度。
從上面的圖片中,很容易可以看出,對 t = 1, 2, ..., k-1, 比較t次:2^(t-1)個。而比較k次的輸入有2^(k-1) + n +1個
這裡k代表最多的比較次數,輸入規模為n,則存在n+1種target輸入是在序列中不存在的,也就是說要比較k次,所以,
比較k次的輸入是2^(k-1) + n + 1。
我們假設 輸入規模n = 2^k -1(n為奇數),並且,各種輸入概率相等,則一共有1/(2n+1)種輸入,那麼
通過上述計算,可以求出平均時間複雜度A(n) = logn+1/2,用漸進符號表示為:O(logn)
時間複雜度的分析,尤其是遞推時間複雜度分析比較麻煩,涉及的方法有迭代法、差消法、遞迴樹法、主定理法等。
相關推薦
演算法時間複雜度分析(1)
如果有錯誤的地方,歡迎大家指正,只希望不要誤導別人。 開篇: 學習演算法時間複雜度分析,首先要對O、o、Ω、ω、Θ這幾個符號有基本的瞭解,下面將給出這幾個符號詳細的定義。 1、大O符號: 定義: 設f和g是定義域為自然數集N上的函式,若存
演算法筆記-複雜度分析1
演算法複雜度分析 是什麼 什麼是演算法複雜度分析? 通過時間和空間兩個維度來評估演算法和資料結構的效能。 用時間複雜度 (時間漸進複雜度) 和空間複雜度 (空間漸進複雜度)兩個概念來描述效能問題,統稱複雜度。 演算法複雜度描述的是演算法執行時間以及佔用空間與資料規模的關聯關係 演算法複
演算法:演算法的概述和演算法時間複雜度分析
演算法:演算法的概述和演算法時間複雜度分析 我是一名在校大學生,學習到了演算法這門課程,想整理一些筆記和大家分享,各位大佬不喜勿噴,僅供參考,希望能對大家有所幫助。 演算法,什麼是演算法 ? 它是求解問題的一系列計算步驟,用來將輸入的資料轉換成輸出結果。我總結關於演算法,有
單鏈表的刪除演算法時間複雜度O(1)和O(n)
平時我們在計算單鏈表的第i個節點刪除時間複雜度時一般認為是O(n),過程如下 1.先從頭節點開始遍歷連結串列,找到第i-1個節點 2.將第i-1節點next指向第i個節點的next 可以看到時間主要花在了遍歷連結串列上 如果我們已經拿到了要刪除的第i個節點Node(i),
遞迴演算法時間複雜度分析
4.1 階乘n!的遞迴演算法的時間複雜度 時間複雜度是由語句頻度分析得來. 遞迴演算法中重複執行的語句主要是呼叫. 所以遞迴演算法的時間複雜度分析主要是分析遞迴演算法中遞迴函式呼叫的次數,並給出其呼叫次數的函式f(n). 如例1中,當n=5時fan(5)的呼叫情況如圖1所示: 從圖1中可以總結
考研中的演算法時間複雜度分析
1.常用的時間複雜度比較關係為O(1) <= O(log2(n)) <= O(n) <= O(nlog2(n)) <= O(n2) <= O(n3) ..... <=O(nk) <= O(2(n))2.具體步驟 1)確定演算法中
一、演算法時間複雜度分析
參考書目:《資料結構與演算法 (java語言班)》 P25 評價演算法的執行時間是通過分析在一定規模下演算法的基本操作完成的,並且我們只對大規模問題的執行時間感興趣。O、Ω、Θ分別定義了時間複雜度的上界、下界、精確階。 計算時間複雜度,最簡單的方式就是計算
演算法時間複雜度分析
演算法時間複雜度分析 在看一個演算法是否優秀時,我們一般都要考慮一個演算法的時間複雜度和空間複雜度。現在隨著空間越來越大,時間複雜度成了一個演算法的重要指標,那麼如何估計一個演算法的時間複雜度呢? 時間複雜度直觀體現 首先看一個時間複雜度不同的兩個演算法,解決同一個問題,會有多大的區別。 下面兩個演算法都是
設任意n個整數存放於陣列A[1..n]中,試編寫演算法,將所有正數排在所有負數前面(要求:演算法時間複雜度為O(n))。
注意陣列的實際長度 #include <iostream> using namespace std; void sort(int A[],int n) { int i=0;//陣列的頭下標 int j,x; j=n-1;//陣列的尾下標 while
常見排序演算法的基本原理、程式碼實現和時間複雜度分析
排序演算法無論是在實際應用還是在工作面試中,都扮演著十分重要的角色。最近剛好在學習演算法導論,所以在這裡對常見的一些排序演算法的基本原理、程式碼實現和時間複雜度分析做一些總結 ,也算是對自己知識的鞏固。 說明: 1.本文所有的結果均按照非降序排列; 2.本文所有的程式均用c++實現,
資料結構與演算法--蠻力法之氣泡排序與時間複雜度分析(java)
蠻力法 蠻力法又稱窮舉法和列舉法,是一種簡單直接地解決問題的方法,常常直接基於問題的描述,所以蠻力法也是最容易應用的方法。但是蠻力法所設計的演算法時間特性往往是比較低的,典型的指數時間演算法一般都是通過蠻力
1. 時間複雜度分析
一. 對資料規模又一個概念 想要在1s內解決問題: O(n2)的演算法可以處理大約104級別的資料 O(n)的演算法可以處理大約10^8級別的資料 O(nlogn)的演算法可以處理大約10^7級別的資料 保險起見,在實際中最好降一個級 空間複雜度 遞
KMP演算法介紹及時間複雜度分析
概念:字串中 一個字元前面的字串 的字首與字尾的最長匹配長度(短的那個字串) 注意:字首與字尾不可以是整個子字串 例如:a b c a b c d , d位置的最長匹配長度為3,abc 與 abc 匹配 Next陣列:長度與字串長度一致,每個位置儲存對應字元的最長匹配長
遞迴演算法的時間複雜度分析
在演算法分析中,當一個演算法中包含遞迴呼叫時,其時間複雜度的分析會轉化為一個遞迴方程求解。實際上,這個問題是數學上求解漸近階的問題,而遞迴方程的形式多種多樣,其求解方法也是不一而足,比較常用的有以下四種方法: (1)代入法(Substitution Method)
排序演算法——希爾排序的圖解、程式碼實現以及時間複雜度分析
希爾排序(Shellsort) 希爾排序是衝破二次時間屏障的第一批演算法之一。 希爾排序通過比較相距一定間隔的元素來工作;各躺比較所用的距離隨著演算法的進行而減小,直到只比較相鄰元素的最後一趟排序為止。由於這個原因,希爾排序有時也叫做縮減增量排序。 希爾排
常用排序演算法穩定性、時間複雜度分析
1、 選擇排序、快速排序、希爾排序、堆排序不是穩定的排序演算法, 氣泡排序、插入排序、歸併排序和基數排序是穩定的排序演算法。 2、研究排序演算法的穩定性有何意義? 首先,排序演算法的穩定性大家應該都知道,通俗地講就是能保證排序前兩個相等的資
淺談直接插入排序演算法思想以及時間複雜度分析
研究意義 直接插入排序是最基本的一種排序演算法,其思想簡單,容易掌握,對後期的學習也有一定的幫助。 必備知識(之後不再敘述) 排序:將一組雜亂無章的資料排列成一個按關鍵字有序的序列。 穩定性:關鍵值相
排序演算法 (穩定性時間複雜度分析)
1、 選擇排序、快速排序、希爾排序、堆排序不是穩定的排序演算法, 氣泡排序、插入排序、歸併排序和基數排序是穩定的排序演算法。 2、研究排序演算法的穩定性有何意義? 首先,排序演算法的穩定性大家應該都知道,通俗地講就是能保證排序前兩個相等的資
資料結構和演算法分析之排序篇--歸併排序(Merge Sort)和常用排序演算法時間複雜度比較(附贈記憶方法)
歸併排序的基本思想 歸併排序法是將兩個或以上的有序表合併成一個新的有序表,即把待排序序列分成若干個子序列,每個子序列是有序的。然後再把有序子序列合併為整體有序序列。注意:一定要是有序序列! 歸併排序例項: 合併方法: 設r[i……n]由兩個有序子表r
JavaScript 演算法之最好、最壞時間複雜度分析
上一篇文章中介紹了複雜度的分析,相信小夥伴們對常見程式碼的時間或者空間複雜度肯定能分析出來了。 思考測試 話不多說,出個題目考考大家,分析下面程式碼的時間複雜度(ps: 雖然說並不會這麼寫) function find(n, x, arr) { let ind = -1;