目錄
- 1. The Gist
- 1.1 為什么要學它(Motivation)
- 1.2 High level idea
- 1.3 4個例子
- 2. Big-Oh Notation
- 2.1 文本定義
- 2.2 圖形定義
- 2.3 數學定義
- 3. 2個例子
- 3.1 k階多項式是O(n^k)
- 3.2 k階多項式不是O(n^(k-1))
- 4. Big Omega and Theta
- 4.1 Big-Omega表示法
- 4.2 Big-theta表示法
- 4.3 Little-O表示法
- 4.4 漸進性表示法的來源
- 5. 幾個額外的例子【可選】
- 5.1 在指數中添加一個常數
- 5.2 指數乘以一個常數
- 5.2 最大值和求和
1. The Gist
1.1 為什么要學它(Motivation)
我們的目的是尋找一種對算法進行衡量的最有效力度,我們希望忽略不重要的細節,例如常數因子和低階項,把注意力集中在算法的運行時間是怎樣隨着輸入長度的增長而增長的,這些任務是通過大O表示法(包括它的近親表示法)的形式完成的,每個程序員都應該掌握這個概念。
它是行業術語漸進性表示法提供了討論算法設計與分析的基本術語,當我們聽到某個程序員談論他的某段代碼以"n的大O時間運行",而另一段代碼,以"n平方的大O時間運行"時,我們需要知道其中的意思。它是區別不同算法的"sweet spot"它有粗放和精細的兩個特征。粗放:忽略了所以我們想要忽略的細節,比如說計算機體系結構,具體選擇的編程語言以及編譯器等方面的細節。精細:可以在不同層次對解決這個問題不同算法進行比較,尤其在巨大輸入情況下,輸入的規模越大,就越需要精妙的算法。
1.2 High level idea
一句話概括漸進性表示法的話,就是忽略常數因子和它的低階項。
為什么我們要忽略常數因子和它的低階項?根據定義,我們把注意力放在大規模的輸入時低階項的作用就幾乎可以忽略了,而大規模的輸入才是需要精妙算法的時候,同時常數因子一般高度依賴於環境的細節,如果我們分析算法時並不想固定於某種特定語言計算機體系結構和編譯器,那么使用不在意的常數因子就會非常合理。不是說忽略的就不重要,什么時候它重要?忽略的意思並不是說常數因子是完全無關緊要的,只不過當我們想要對解決同一個問題的一些不同方法進行比較的時候,漸進性表示法往往是正確的工具,它能幫助我們理解哪種算法的性能最佳,尤其是當輸入規模非常大時,但我們確定了某個問題的最佳高級算法后,可能還想進一步優化常數因子和低階項。
1.3 4個例子
這里有4個比較簡單的例子,如果是第一次接觸這個概念的朋友可以自己試着做一下,求每個例子的漸進性運行時間。后台回復【漸進性表示法】查看答案。Algorithm 1數組A中包含整數t嗎?
1: for i = 1 to n do 2: if A[i] == t then 3: Return TRUE 4: Return FALSE
Algorithm 2給定數組A,B和整數t,A或B中包含t嗎?
1: for i = 1 to n do 2: if A[i] == t then 3: Return TRUE 4: for i = 1 to n do 5: if B[i] == t then 6: Return TRUE 7: Return FALSE
Algorithm 3數組A,B有相同的元素嗎?
1: for i = 1 to n do 2: for j = 1 to n do 3: if A[i] == B[j] then 4: Return TRUE 5: Return FALSE
Algorithm 4數組A中有重復的元素嗎?
1: for i = 1 to n do 2: for j = i+1 to n do 3: if A[i] == A [j] then 4: Return TRUE 5: Return FALSE
2. Big-Oh Notation
2.1 文本定義
大O表示法關注的是定義在正整數n = 1,2,3..上的函數T(n),T(n)總是表示某個算法的最壞情況運行時間的上界,那么當我們說T(n)=O(f(n))的時候表示什么意思呢?
T(n)=O(f(n))當且僅當T(n)的最終上界是f(n)的一個常數積。
2.2 圖形定義
由下圖我們看到T(n)的上界並不是由f(n)決定的,是由f(n)乘以3所形成的上面那個虛線決定的,當n的值足夠大時超過n0這個分界點,之后它的值就會大於T(n),所以T(n)實際上最終是由f(n)的常數積確定上界,我們就可以說T(n)=O(f(n))。
這里的常數c滿足f(n)的常數倍,常數n0滿足最終。
2.3 數學定義
T(n)=O(f(n))表示當且僅當存在正常數c和n0,對所有的,不等式都成立。這個數學公式實際上是對文本定義的直接翻譯。“對所有的n大於等於n0”表示這個不等式只需要當n足夠大的時候(n0確定了具體的大小)最終能夠成立,而在圖中常數c對應的是3,n0對應的是函數T(n)和cf(n)之間的分界值.warning:一個警告,當我們說c和n0是常數,意思是它並不依賴於n,比如說圖中的c和n0是固定的數字,像是300,1000,如果我們在證明中看到n0=n,或者c=log(n)這樣的說法,它就是與n有關的,就不是常數值了。
3. 2個例子
3.1 k階多項式是O(n^k)
這個命題表示在多項式的大O表示法中,我們需要關注的是出現在多項式的最高階。因此大O表示法確實忽略了常數因子和低階項。簡化版的證明過程如下
以下是詳細版本的解釋。根據大O表示法的數學定義,我們需要的是找到一對正整數c和n0,我們先假設這兩個常量的值: n0=1,c等於所有系數的絕對值之和:。這兩個數都與n無關,現在我們需要證明選擇的這兩個常量滿足不等式,即對所有,都有。首先我們看看T(n)的定義:如果我們在右邊取每個系數的絕對值,這個表達式只會變得更大。(只會比更大,由於是正數,只會比更大),於是:既然系數是非負數,我們也可以用類似的技巧讓n的不同乘方轉換成n的公共乘方。由於,對於每個,只會比更大,由於是非負正數,所以只會比更大。就意味着:對於每個,這個不等式是成立的,這就是我們想要的證明結果。
3.2 k階多項式不是O(n^k-1)
它表示不同階的多項式的大O表示法是不同的。我們可以用反證法,假設結論的相反結論是對的,並在這個假設上進行一系列的邏輯正確的步驟,最后推導出出錯。簡單的證明過程如下
以下是詳細的文字解釋。因此假設=,那么它意味着什么呢?的最終上界是的一個常數積確定的。也就是說,存在常數c和,對於所有的,都存在由於n是正數,我們可以從兩邊消去,於是對於所有的,都存在。相當於說c比每個正整數都要大,這是明顯錯誤的(可以取n的值是c+1向上取最接近的整數),這就說明原來的假設是錯誤的。
4. Big Omega and Theta
4.1 Big-Omega表示法
文字表示法就是,當且僅當T(n)的下界是由f(n)的一個常數積所確定,那么T(n)就是另一個函數f(n)的大。數學定義如下:
當且僅當存在正常數c和,使得對於每一個,都有。對應的圖形式如下:
f(n)並沒有確定T(n)的下界,但是如果把它乘以常數,那么就是在臨界點的右邊確定了T(n)的下界。
4.2 Big-theta表示法
它可以類比於“等於”,相當於同時滿足和,相當於T(n)被夾在f(n)的兩個不同的常數積之間。數學定義如下:
當且僅當存在正常數,使得當的時候,有。
4.3 Little-O表示法
T(n)=o(f(n))表示當且僅當對所有c>0的常數,存在常數n0,對所有的,不等式都成立。
4.4 漸進性表示法的來源
漸進表示法不是由計算機科學家發明的,是開始於數論。
5. 幾個額外的例子【可選】
5.1 在指數中添加一個常數
這個例子是說,一個函數的指數與一個常數相加,並不會改變這個函數的漸進性時間增長率。簡化的證明過程:
更詳細的解釋:要證明這個,我們需要找到合適的正常數c和,使得對於所有的,T(n)的最大值是,我們來對它進行反向工程。
我們在尋找一個推導方式,不斷的放大T(n)使得它是的常數倍,我們看到T(n)的指數里有個10,很自然的想着把它分出去:我們發現右邊就是的常數倍,這就提醒我們c取1024。假設選擇這個c,那么對於所有的都有,因此我們取,那么就證明出來了。
5.2 指數乘以一個常數
這個命題的意思是,把一個指數函數的指數和一個常數相乘改變了它的漸進性增長率。簡化的證明過程:
更詳細的文字:這個用反證法來證明,它的相反結論是對的,就是。根據大O的定義,存在正常數c和,對於所有的,都有,因為是個正數,所以我們可以兩邊去掉,就得,這個是錯誤的,因為右邊是個固定的數,而左邊是隨着n增加而無限增加的,說明我們的假設是錯誤的,這就證明得了原問題。
5.2 最大值和求和
這個例子表示從漸進性的角度,取兩個非負數的逐點最大值和取她們的和沒有什么差別。簡化的證明過程:
的含義表示T(n)最終位於f(n)的兩個不同常數倍之間。我們需要三個常數:,,,后面兩個對應較大倍數和較小倍數。我們對幾個數進行反向工程。任何一個正整數都存在以下關系:因為不等式的右邊就是左邊的數加上另一個非負數(f(n)和g(n)中較小的那個數)。類似的因為不等式的左邊是f(n)和g(n)中較大那個的兩倍,把兩個不等式合在一起就是,對每個,都有確實位於兩個不同倍數之間,相當於今日互動
歡迎在評論區留下不懂的~