P問題、NP問題、NPC、NP-Hard、P=NP?

目錄

  • 時間復雜度與多項式時間
  • 確定性算法與非確定性算法
  • 判定性問題
  • 規約/約化
  • P問題
  • NP問題
  • NPC問題
  • P=NP?
  • NP難問題
  • 求解難問題

# 時間復雜度與多項式時間

在計算機科學中,算法的時間復雜度是一個函數,它定性描述該算法的運行時間。這是一個代表算法輸入值的字符串的長度的函數。時間復雜度常用大O符號表述,不包括這個函數的低階項和首項系數。使用這種方式時,時間復雜度可被稱為是漸近的,亦即考察輸入值大小趨近無窮時的情況。 —— 維基百科

  • 常數級復雜度:不管數據有多大,程序處理所花的時間始終是那么多的,我們就說這個程序很好,具有O(1)的時間復雜度,也稱常數級復雜度;
  • 線性級復雜度:數據規模變得有多大,花的時間也跟著變得有多長,比如找n個數中的最大值這個程序的時間復雜度就是O(n),為線性級復雜度
  • 平方級復雜度:像冒泡排序、插入排序等,數據擴大2倍,時間變慢4倍的,時間復雜度是O(n^2),為平方級復雜度。
  • 指數級復雜度:還有一些窮舉類的算法,所需時間長度成幾何階數上漲,這就是O(a^n)的指數級復雜度(EXPTIME算法)
  • 甚至還存在O(n!)的階乘級復雜度。

容易看出,前面的幾類復雜度被分為兩種級別,其中后者的復雜度無論如何都遠遠大于前者。像O(1),O(ln(n)),O(n^a)等,我們把它叫做多項式級復雜度,因為它的規模n出現在底數的位置;
另一種像是O(a^n)O(n!)等,它是非多項式級的復雜度,其復雜度計算機往往不能承受。當我們在解決一個問題時,我們選擇的算法通常都需要是多項式級的復雜度,非多項式級的復雜度需要的時間太多,往往會超時,除非是數據規模非常小。

對于同一個問題,不同的算法可能會產生不同的復雜度。最典型的例子就是排序,對于n個整數,選擇排序和冒泡排序的復雜度為O(n^2),快速排序的復雜度為O(nlogn),而使用基數排序的復雜度僅為O(mn)

# 確定性算法:

設A是求解問題B的一個解決算法,在算法的整個執行過程中,每一步都能得到一個確定的解,這樣的算法就是確定性算法。

# 非確定性算法:

設A是求解問題B的一個解決算法,它將問題分解成兩部分,分別為猜測階段和驗證階段,其中

  • 猜測階段:在這個階段,對問題的一個特定的輸入實例x產生一個任意字符串y,在算法的每一次運行時,y的值可能不同,因此,猜測以一種非確定的形式工作。
  • 驗證階段:在這個階段,用一個確定性算法(有限時間內)驗證。①檢查在猜測階段產生的y是否是合適的形式,如果不是,則算法停下來并得到no;② 如果y是合適的形式,則驗證它是否是問題的解,如果是,則算法停下來并得到yes,否則算法停下來并得到no。它是驗證所猜測的解的正確性。

# 判定問題Decision question

判定問題是數理邏輯中的一個重要問題。它表現為尋求一種能行的方法、一種機械的程序或者算法,從而能夠對 某類問題中的任何一個 在有窮步驟內 確定其是否具有某一特定的性質。
簡而言之:答案是yes或者no的問題

# 規約/約化

問題A可以約化為問題B,稱為“問題A可規約為問題B”,可以理解為問題B的解一定就是問題A的解,因此解決A不會難于解決B。由此可知問題B的時間復雜度一定大于等于問題A。

《算法導論》中有一個例子:現在有兩個問題:求解一個一元一次方程和求解一個一元二次方程。那么我們說,前者可以規約為后者,意即知道如何解一個一元二次方程那么一定能解出一元一次方程。我們可以寫出兩個程序分別對應兩個問題,那么我們能找到一個“規則”,按照這個規則把解一元一次方程程序的輸入數據變一下,用在解一元二次方程的程序上,兩個程序總能得到一樣的結果。這個規則即是:兩個方程的對應項系數不變,一元二次方程的二次項系數為0。

從規約的定義中我們看到,一個問題規約為另一個問題,時間復雜度增加了,問題的應用范圍也增大了。通過對某些問題的不斷規約,我們能夠不斷尋找復雜度更高,但應用范圍更廣的算法來代替復雜度雖然低,但只能用于很小的一類問題的算法。存在這樣一個NP問題,所有的NP問題都可以約化成它。換句話說,只要解決了這個問題,那么所有的NP問題都解決了。這種問題的存在難以置信,并且更加不可思議的是,這種問題不只一個,它有很多個,它是一類問題。這一類問題就是傳說中的NPC問題,也就是NP-完全問題。

# P問題

Polynomial-time問題,能夠在 多項式時間內用算法求解的問題 。

P問題意味著計算機能夠在有限時間內完成計算。整數排序問題就是P問題,不管你是采用冒泡排序還是快速排序,也無論你是對于10個整數排序還是10億個整數排序。

# NP問題

Nondeterministic polynomial-time問題,即 非確定性多項式時間,指不確定是否存在多項式時間的求解算法,但可以在多項式時間內驗證一個猜測解的正確性的問題。

也就是說,不能判定這個問題到底有沒有解,而是猜出一個解來在多項式時間內證明這個解是否正確。即該問題的猜測過程是不確定的,而對其某一個解的驗證則能夠在多項式時間內完成。P類問題屬于NP問題,但NP類問題不一定屬于P類問題。

1、N皇后問題。在學習數據結構和算法這門課時,有一個比較經典的問題叫做“八皇后問題”,它要求在一個國際象棋的棋盤上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處于同一行、同一列或同一斜線上。這里我們把棋盤擴展到N*N,并在其中擺放N個皇后,其他要求一樣。這個問題就是一個NP問題,至今為止暫時還沒有多項式時間的解法。不過我們很容易驗證一個解是否滿足要求:對于這N個皇后中的每一個,都檢查其所在行,所在列和兩個斜線方向是否有其他皇后,即可驗證這個解是否是正解,這種驗證方法的復雜度為O(n)。

2、劃分問題。以下38個整數的和為2000000:
14175,15055,16616,17495,18072,19390,19731,22161,23320,23717,26343,28725,29127,32257,40020,41867,43155,46298,56734,
57176,58306,61848,65825,66042,68634,69189,72936,74287,74537,81942,82027,82623,82802,82988,90467,97042,97507,99564

要求把它們平均分為兩組,每組的19個數字之和都是1000000.

求解這個題其實并不容易,把這38個數分為兩組總共有17672631900種方式。也許求出結果對于當今的計算機來說并非遙不可及,程序稍微優化一些其實并不用枚舉其中的每一種情況(比如取到前17個數就已經超過1000000時,不用再取第18個和第19個數了)。然而如果是把2000個數分為兩組呢?恐怕世界上最好的計算機也無能為力了。

不過,驗證這個問題的解卻非常容易,只需檢驗一下在同一組的19個數的和是不是1000000即可。

# NPC問題(NP完全問題)

Non-deterministic Polynomial complete problem ,存在這樣一個NP問題,所有的NP問題都可以約化成它。換句話說,只要解決了這個問題,那么所有的NP問題都解決了。NPC包含了NP中最難的問題。

其定義要滿足2個條件:

  • 它是一個NP問題;
  • 所有NP問題都能規約到它。

在1971年,斯蒂芬·庫克找到了第一個這樣的問題:可滿足性問題。簡要來說,就是對于N個布爾類型的變量,它們之間采用“與”,“或”,“非”這樣的邏輯運算符連接,那么這些變量能否找到一組合適的取值,使得最終的運算結果為真。與之相同的是邏輯電路問題,它其實就是可滿足性問題的數字電路實現,用高電平和低電平表示真和假,用與門,或門和非門表示邏輯運算符。

伯克利的教授理查德·卡普在讀過庫克的論文之后,發現有一種方法可以把可滿足性問題歸約到團問題。團問題大致是這樣一類問題:對于任意兩個人,要么是微信好友,要么不是微信好友。那么能否找到一個人數為50個人的團體,使得他們兩兩之間彼此都是微信好友?因為庫克證明了可滿足性問題是NP問題中最難的問題,而卡普得到的則是,團問題不比可滿足性問題要簡單,至少它們一樣難。卡普不僅證明了團問題是NP問題中最難的一個,而且他還找到了19個同樣難度的重要問題,比如哈密頓回路,旅行商問題,最大割問題等等。1972年,他在他的論文《Reducibility Among Combinatorial Problems》中,提出了這21個NP中最難的問題。

那么這些問題叫什么名字呢?在1973年,曾經做了一次投票調查,在投票中出現了幾個候選項——herculean, formidable, arduous, intractable, obstinate等等,不過最終勝出的還是”NP-Complete”(NP完全)。complete表示完全或者完備,一個事實集合被稱為是完備的,表明它能解釋某些邏輯系統的所有真命題。這也比較符合解決了NP完全問題,就能解決所有其他的NP問題的事實。NP完全問題也簡稱為NPC問題。

# P=NP?

P=NP? 通常被認為是計算機科學最重要的問題。再回顧一下P、NP的定義:

  • P是可在多項式時間內用 確定算法求解的問題。
  • NP是可在多項式時間內用 不確定算法求解的問題。
    前面知道,NP包含P,所以“P=NP?”問題的關鍵,就在于P是否也包含了NP。也就是說,如果使用確定算法,能否在多項式時間之內,解決所有不確定性算法能在多項式時間內解決的問題。

我們再來細看一下什么是多項式時間(Polynomial time)。我們都知道,n^2是多項式,n^{1000000}也是多項式。多項式與多項式之間,卻有天壤之別。把解決問題所需要的時間,用“多項式”這么籠統的概念來描述,其實是非常不準確的做法。在實際的大規模應用中,n^2的算法都嫌慢。能找到“多項式時間”的算法,根本不能說明任何問題。對此,理論家們喜歡說,就算再大的多項式(比如 n^{1000000},也不能和再小的指數函數(比如1.0001^n)相比。因為總是“存在”一個M,當n>M的時候,1.0001^n會超過n^{1000000}
可是問題的關鍵,卻不在于M的“存在”,而在于它的“大小”。如果你的輸入必須達到天文數字才能讓指數函數超過多項式的話,那么還不如就用指數復雜度的算法。所以,“P=NP?”這問題的錯誤就在于,它并沒有針對我們的實際需要,而是首先假設了我們有“無窮大”的輸入,有“無窮多”的時間和耐心,可以讓多項式時間的算法“最終”得到優勢。

# NP難問題

Non-deterministic Polynomial hard problem(NPH)問題,如果所有NP問題都可歸約成某個問題,則該問題稱為NP難問題。( 滿足NPC問題定義的第二條但不一定要滿足第一條)

NPC問題是NP難問題的一個子集。網上看到過一幅表明P問題,NP問題,NPC問題和NP難問題的關系圖,覺得非常棒,這里引用過來。

前面說過如果P=NP,那么所有的NP問題都存在有效的解決方案,而對于NP難問題來說,即使P=NP,也不一定存在有效的解決方案。

# 求解難問題

對于一個NP問題甚至是NP難問題,通常都無法找到有效的解決方案,于是隔壁老王跟老板說:這個問題我解決不了,并且你找任何人都解決不了。老板想了想之后,把隔壁老王開除掉了,畢竟誰都解決不了,那就干脆不雇傭人好了,還能省點兒錢。

幾天之后,有個叫小明的同學跟老板說:你交給隔壁老王的那個問題要求有些太高,現在沒有人能解決。但是如果把要求稍微降低些,我能給你提供一個不錯的解決方案。于是老板想了想覺得可以接受,于是就雇傭了小明,頂替隔壁老王之前的崗位。

在遇到幾乎不可能做到的問題時,我們通常會選擇退而求其次,尋找一個還能說得過去的方案。

比如我們要尋找從國貿到中關村的最短距離(當然這個問題使用窮舉法也不會算太長時間,僅僅是舉個栗子。如果你覺得不過癮,可以考慮從杭州西湖到中關村的最短距離),由于中間的道路比較繁雜,窮舉起來數目非常多,于是我們可以采用一種優化的方案:約定中途需要經過西直門。首先尋找從國貿到西直門的最短距離,然后尋找從西直門到中關村的最短距離。顯然從國貿到中關村的最短距離,一定不會比從國貿到西直門的最短距離 加上 從西直門到中關村的最短距離要長。這么做雖然得到的可能不是最短距離的出行方案,不過卻可以縮短我們的搜索范圍,大大提高了解決問題的效率。當然,你還可以在國貿和西直門之間鎖定另外一個地方,比如南鑼鼓巷。很多地圖軟件就是采用這樣的方案提供路線的。

上面提到的機器學習中的特征選擇問題,通常采取的做法是使用前向搜索這種啟發式算法:每次從所有未選擇的特征中選擇一個使評價結果最佳的特征,加入到備選子集中,直到加入任何特征時評價結果無法更好,或者達到了限定的特征數。這樣做不能保證達到全局最優,不過卻使得實現起來變得可能。

參考鏈接

鏈接1:https://blog.csdn.net/qq_29176963/article/details/82776543
鏈接2:https://blog.csdn.net/liusiqian0209/article/details/49837447

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容