討厭演算法的程式設計師 4 - 時間複雜度

weixin_33762321發表於2017-05-20

討厭演算法的程式設計師系列入口

增長量級

4593922-3b991d95c636319b.png
函式的增長量級

上一篇演算法分析基礎中,我們分析了插入排序,知道了其最好情況下的執行時間為T(n) = an + b,最差情況下的執行時間為T(n) = an2 + bn + c。表示式中的常量a、b和c(實際上都是依賴每行程式碼的執行時間ci)進一步抽象了每行程式碼的執行時間,而凸顯出輸入規模n與執行時間T的關係。

然而這樣還不夠,還有進一步抽象的空間:即人們真正感興趣的是執行時間隨輸入規模增長的增長率或增長量級。也就是說,當n越來越大時,T的增長是何種量級?我們知道,當n的值很大時,低階項對T的貢獻就沒那麼重要了,同時,最重要的高階項的常量係數對T的貢獻也沒那麼重要了。

對於插入排序最差情況來說,當忽略掉低階項以及高階項的常數係數,就只剩下了n2。插入排序最差情況的執行時間,可記做T(n) = Θ(n2),其中Θ稱作漸進記號,這種簡化成為漸進分析。

漸進分析強調的是,對於足夠大的輸入,執行時間中的倍增常量和低階項被輸入規模本身的影響所支配。儘管有時在一個小輸入下,一個執行時間具有較低增長量級的演算法(比如T(n) = 5n)),比一個執行時間具有較高增長量級的演算法(比如T(n) = n2),需要更多的時間。

時間複雜度

《演算法導論》中的整個第一部分(第1章到第5章),一直沒有發現“時間複雜度”這個我們非常熟悉的名詞及定義(英文版未考證),儘管書中一步步引匯出的“演算法執行時間”,以及“漸進記號”其實就是在說“時間複雜度”。到了第二部分(第6章),又開篇冒出了“時間複雜度”這個詞,反而有點不適。這可能與中文版是由7個人翻譯的有關。

剛好手邊有程傑的《大話資料結構》一書,這裡引用下其對“時間複雜度”的定義,算是有個交待。

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

漸進記號

細心的讀者可能發現了,上面的增長量級一節與時間複雜度一節分別用到了兩種不同的漸進符號,Θ和Ο,前者發音Theta,後者發音Omicron,它們都是希臘字母。

通常所說的演算法時間複雜度不都是用的後一種Ο麼(有時也叫大Οmicron)?

到這裡,《演算法導論》的厲害之處就彰顯無餘了。它不僅介紹了Θ和Ο,還介紹了Ω(大Omega),ο(小Omicron),ω(小Omega)5種不同的漸進記號,每種記號都體現了不同的漸進分析方法。

出於實用性的考慮,這裡只簡單說下Θ與Ο的異同。對其餘漸進符號,用到之處會再解釋。

對於T(n) = an2 + bn + c, 既可以記作T(n) = Θ(n2),也可以記作 T(n) = Ο(n2)。

對於T(n) = an + b, 既可以記作T(n) = Θ(n),也可以記作T(n) = Ο(n),還可以記作T(n) = Ο(n2)。

這是因為Θ是一種緊確性的表示,而Ο是一種非緊確性、只描述了上限的表示。

《演算法導論》中的翻譯的這個詞“緊確”,還是很形象的。我再說的直白點,就是繪製出的函式圖形,是否比較“貼合”。

我們看到的大部分書中都是在用Ο(大Omicron)表示時間複雜度,但通常都是選擇了一個緊確性的函式。比如說,T(n) = an + b,T(n) = Ο(n),T(n) = Ο(n2)都對,但是會選擇前者T(n) = Ο(n)。

上一篇 3 演算法分析基礎
下一篇 5 合併演算法


共享協議:署名-非商業性使用-禁止演繹(CC BY-NC-ND 3.0 CN)
轉載請註明:作者黑猿大叔(簡書)

相關文章