來源:Matrix67
什么是時間復雜度?
關鍵字:多項式級復雜度
時間復雜度並不是表示一個程序解決問題需要花多少時間,而是當問題規模擴大后,程序需要的時間長度增長得有多快。也就是說,對於高速處理數據的計算機來說,處理某一個特定數據的效率不能衡量一個程序的好壞,而應該看當這個數據的規模變大到數百倍后,程序運行時間是否還是一樣,或者也跟着慢了數百倍,或者變慢了數萬倍。
不管數據有多大,程序處理花的時間始終是那么多的,我們就說這個程序很好,具有O(1)的時間復雜度,也稱常數級復雜度;
數據規模變得有多大,花的時間也跟着變得有多長,這個程序的時間復雜度就是O(n),比如找n個數中的最大值;
而像冒泡排序、插入排序等,數據擴大2倍,時間變慢4倍的,屬於O(n2)的復雜度。
還有一些窮舉類的算法,所需時間長度成幾何階數上漲,這就是O(an)的指數級復雜度,甚至O(n!)的階乘級復雜度。
不會存在O(2*n2)的復雜度,因為前面的那個“2”是系數,根本不會影響到整個程序的時間增長。同樣地,O (n3+n2)的復雜度也就是O(n3)的復雜度。因此,我們會說,一個O(0.01*n3)的程序的效率比O(100*n2)的效率低,盡管在n很小的時候,前者優於后者,但后者時間隨數據規模增長得慢,最終O(n^3)的復雜度將遠遠超過O(n^2)。我們也說,O(n^100)的復雜度小於O(1.01^n)的復雜度。
容易看出,前面的幾類復雜度被分為兩種級別,其中后者的復雜度無論如何都遠遠大於前者:
一種是O(1),O(log(n)),O(na)等,我們把它叫做多項式級的復雜度,因為它的規模n出現在底數的位置;
另一種是O(an)和O(n!)型復雜度,它是非多項式級的,其復雜度計算機往往不能承受。
當我們在解決一個問題時,我們選擇的算法通常都需要是多項式級的復雜度,非多項式級的復雜度需要的時間太多,往往會超時,除非是數據規模非常小。
多項式時間
來源:沈萬馬
什么是多項式?
對於變量n,5n2+2n+1這種就叫做多項式。前面再加上n3甚至一路增加到nm,只要m是個常量,就都是多項式。因為這樣的式子合並同類項什么的簡化到最后還是會有好幾個含n的項,所以叫做多項式。
什么是問題大小?
我們要解決一個問題,這個問題里面有n個“東西”要處理,這個問題的大小就是n。比方說,我們要把5、7、9這三個數字排序,問題大小就是3。我們要把全世界人類里面的男的找出來,問題大小就是全世界人口數。
什么是多項式倍數?
這個倍數是指,對於一個變量n,有這樣一個倍數,它的值是n的一個多項式。比方說,我們假設n=5,那么n2+10=52+10=35,這個35就是n的一個多項式倍數。因為對於n有無限多種多項式組合,所以它也就有無窮多個多項式倍數。
多項式時間
多項式倍數之所以特殊,主要是由於其值隨n增大而加速增大的特性。如果是常數時間的話,意思就是無論n是什么值運算所花時間都一樣。線性時間則是說多大n就花多少時間。多項式時間則意味着隨着n增大,n每增加1所花的時間增長越來越多。對於n2-3這樣一個多項式時間來說,n=2的時候可能只要花1的時間,甚至低於線性時間,但n=4的時候可能就要花13的時間了,可以想象再大一些這個數值會變得巨大。但是它又不及指數時間增長快(mn),且mn不能寫成多項式形式,所以它又和多項式時間有區別。
不可解問題
會不會所有的問題都可以找到復雜度為多項式級的算法呢?很遺憾,答案是否定的。有些問題甚至根本不可能找到一個正確的算法來,這稱之為“不可解問題”(Undecidable Decision Problem)。The Halting Problem就是一個著名的不可解問題
P類問題
如果一個問題可以找到一個能在多項式的時間里解決它的算法,那么這個問題就屬於P問題。P是英文單詞多項式的第一個字母
NP問題
NP問題不是非P類問題。NP問題是指可以在多項式的時間里驗證一個解的問題。NP問題的另一個定義是,可以在多項式的時間里猜出一個解的問題。
換句話說,就是在解決一個問題時,找一個解很困難,而驗證(猜測)一個解很容易。
所有的P類問題都是NP問題,也就是說,能多項式地解決一個問題,必然能多項式地驗證一個問題的解
NPC問題
人們普遍認為,P=NP不成立,也就是說,多數人相信,存在至少一個不可能有多項式級復雜度的算法的NP問題。
人們如此堅信P≠NP是有原因的,就是在研究NP問題的過程中找出了一類非常特殊的NP問題叫做NP-完全問題,也即所謂的 NPC問題。C是英文單詞“完全”的第一個字母。正是NPC問題的存在,使人們相信P≠NP
約化/規約
簡單地說,一個問題A可以約化為問題B的含義即是,可以用問題B的解法解決問題A,或者說,問題A可以“變成”問題B
《算法導論》上舉了這么一個例子。比如說,現在有兩個問題:求解一個一元一次方程和求解一個一元二次方程。那么我們說,前者可以約化為后者,意即知道如何解一個一元二次方程那么一定能解出一元一次方程。我們可以寫出兩個程序分別對應兩個問題,那么我們能找到一個“規則”,按照這個規則把解一元一次方程程序的輸入數據變一下,用在解一元二次方程的程序上,兩個程序總能得到一樣的結果。這個規則即是:兩個方程的對應項系數不變,一元二次方程的二次項系數為0。按照這個規則把前一個問題轉換成后一個問題,兩個問題就等價了
“問題A可約化為問題B”有一個重要的直觀意義:B的時間復雜度高於或者等於A的時間復雜度。也就是說,問題A不比問題B難。這很容易理解。既然問題A能用問題B來解決,倘若B的時間復雜度比A的時間復雜度還低了,那A的算法就可以改進為B的算法,兩者的時間復雜度還是相同。正如解一元二次方程比解一元一次方程難,因為解決前者的方法可以用來解決后者。
很顯然,約化具有一項重要的性質:約化具有傳遞性。如果問題A可約化為問題B,問題B可約化為問題C,則問題A一定可約化為問題C。
從約化的定義中我們看到,一個問題約化為另一個問題,時間復雜度增加了,問題的應用范圍也增大了。通過對某些問題的不斷約化,我們能夠不斷尋找復雜度更高,但應用范圍更廣的算法來代替復雜度雖然低,但只能用於很小的一類問題的算法。
再回想前面講的P和NP問題,聯想起約化的傳遞性,自然地,我們會想問,如果不斷地約化上去,不斷找到能“通吃”若干小NP問題的一個稍復雜的大NP問題,那么最后是否有可能找到一個時間復雜度最高,並且能“通吃”所有的 NP問題的這樣一個超級NP問題?答案居然是肯定的。也就是說,存在這樣一個NP問題,所有的NP問題都可以約化成它。換句話說,只要解決了這個問題,那么所有的NP問題都解決了。這種問題的存在難以置信,並且更加不可思議的是,這種問題不只一個,它有很多個,它是一類問題。這一類問題就是傳說中的NPC 問題,也就是NP-完全問題。
NPC問題的定義非常簡單。同時滿足下面兩個條件的問題就是NPC問題:
首先,它得是一個NP問題;
然后,所有的NP問題都可以約化到它。
證明一個問題是 NPC問題也很簡單。先證明它至少是一個NP問題,再證明其中一個已知的NPC問題能約化到它(由約化的傳遞性,則NPC問題定義的第二條也得以滿足),這樣就可以說它是NPC問題了。既然所有的NP問題都能約化成NPC問題,那么只要任意一個NPC問題找到了一個多項式的算法,那么所有的NP問題都能用這個算法解決了,NP也就等於P 了。