簡明解釋演算法中的大O符號

2021-09-01 21:55:12 字數 2995 閱讀 8969

大o符號是一種演算法複雜度的相對表示方式。

這個句子裡有一些重要而嚴謹的用詞:

我所能想到的大o符號最好的例子就是做算術。拿兩個數字(123456和789012)舉例。我們在學校裡學到的基本算術操作是:

它們中每乙個都是一次操作或乙個問題。為它們求解的方法就被叫做演算法(algorithm)

加法是最簡單的了。你把加數排成行,按列加上每個數字,把所加得的數的末位數字寫到結果裡。所加得的數的十位及其以上的數字轉入下一列的計算中。

讓我們假設在演算法中,加上這些數是計算開銷最大的操作。合乎情理的說,為了把這兩個數加起來我們必須要加6次數字(並且可能進製到第7次)。如果我們把兩個100位數相加,我們必須做100次加法操作。如果我們把兩個10,000位數相加,我們必須做10,000次加法操作。

看到這裡的模式了嗎?複雜度complexity,就是操作的數量),對於加法中較大數的數字個數n,是直接成比例的。我們稱這為o(n)或者線性複雜度(linear complexity)

除了借位替代了進製,減法也是相似的。

乘法就不同了。你把乘數排成行,取放在下面的乘數的第1個數字,把它逆序乘以上面乘數的每乙個數字。下面乘數的其餘數字也這樣做。所以為了乘我們的兩個6位數乘數,我們必須做36次乘法操作。我們還需要做10或11次列的加法操作來得到最終結果。

如果我們有兩個100位數相乘,我們需要做10,000次乘法操作和200次加法操作。兩個100萬位數相乘,我們需要做1萬億(1012)次乘法操作和200萬次加法操作。

作為n平方的演算法衡量尺度,這就是o(n2),即平方複雜度(quadratic complexity)。現在是時候介紹另乙個重要概念了:

我們只關心複雜度最重要的部分。

敏銳的人可能已意識到,我們可以把操作次數表示為:n2 + 2n。但正如你所看到的,我們的兩個100萬位數相乘的例子,第二個 2n 無關緊要(在那個階段,2n只佔操作總量的0.0002%)。

有人注意到我們在這裡假設場景為最壞的情況。當我們做6位數乘法時,如果其中乙個是4位數另乙個是6位數,那麼我們只需做24次乘法操作。然而,對於那個』n',我們仍然計算最壞情況,即乘數都是6位數的情況。因此,大o符號是關於乙個演算法的最壞情況的。

我所能想到的下乙個最棒的例子就是**簿,通常叫做白頁**簿或者其它類似名字,因國而異。但我要談論的是這種**薄,這種**薄把人按這樣的順序排列:姓、縮寫或名、位址、然後是**號碼。

現在,如果你要指示計算機在乙個包含1,000,000個名字的**簿中查詢」john smith」的**號碼,你會怎麼做?忽略也許你能猜測出s從**簿**開始的事實(假設你不能猜測),你會怎麼做?

一種典型的實現也許是,開啟**簿的正中間,取第500,000條記錄,把它和」smith」進行比較。如果這恰好就是」smith,john」,那我們真幸運。然而,」john smith」更有可能在其前面或後面。如果在後面,那麼我們把**簿後面一半從中間劃分開,然後重複之前的過程;如果在前面,那麼我們把第一半從中間劃分開,然後重複之前的過程。以此類推。

這種演算法叫做二分搜尋(binary search)。不論你是否意識到,它在程式設計中每天都用到。

因此,如果你想要在包含100萬名字的**簿中查詢乙個名字,事實上,通過這種演算法,最多20次,你能找到任何名字。在比較搜尋演算法中,我們決定把比較操作作為我們的』n'。

這簡直好得難以置信,不是嗎?

用大o術語就是o(log n),即對數複雜度(logarithmic complexity)。現在問題中的對數可以是ln(底數為e),log10,log2 或者以其它為底數,這無關緊要,它仍然是o(log n),正如o(2n2) 和 o(100n2) 都記為 o(n2)。

現在,值得花時間說明一下,對於演算法,大o符號能夠被用於決定3種情況:

通常我們不關心最好情況。我們對期望和最壞情況感興趣。有時,期望情況更重要,有時最壞情況更重要。

回到**簿的例子上來。

你從第乙個名字開始比較號碼。如果吻合,很棒,如果不吻合,你移到下一條記錄。你必須這樣做,因為**簿是無序(unordered)的(**號碼的排列是無序的)。

因此,查詢乙個名字:

這是電腦科學中值得提到的乙個相當有名的問題。在這個問題中,有n個城鎮,每個城鎮通過道路與1個或多個其它城鎮相連,道路的路程是確定的。旅行商問題就是找出訪問每個城鎮的最短路線。

聽起來很簡單?再想想。

如果有3個城鎮a、b、c,兩兩之間都有道路,那麼你可以這樣走:

好吧,事實上,實際路線比上面的少,因為一些路線是等價的(例如,a -> b -> c 和 c -> b -> a 是等價的,因為它們使用同一條路線,只是方向相反)。

所以,事實上,這裡有3條可能的路徑。

這是乙個被叫做階乘(factorial)的數**算函式。大體上:

所以旅行商問題的大o符號表示是o(n!),即階乘(factorial)或組合複雜度(combinatorial complexity)

當你有200個城鎮的時候,使用傳統計算機,那麼全世界已經沒有足夠的時間來解決這個問題了。

現在,有一些要思考的東西。

另乙個我想要快速提及的要點是,任何複雜度為o(na)的演算法被稱為有多項式複雜度(polynomial complexity),或可以在多項式時間(polynomial time)內解決。

傳統計算機能解決可以在多項式時間內解決的難題。世界上有些東西就建立在這一基礎上。公鑰加密是個極好例子。找到乙個很大的數的兩個素因子是困難的,如果不困難,那麼我們就不能使用公鑰加密系統了。

總之,這就是我對大o符號的解釋

O符號的簡明解釋

這是在stackoverflow的關於 演算法複雜度 的經典問答。將此文翻譯並分享下。問 by arec barrwin 大o符號的簡明英語解釋 大o符號的簡明英語解釋是什麼?用盡可能少的形式定義和簡單的數 算。答 by cletus 注意,所有人幾乎都會混淆大o符號 有上界 和theta符號 有兩...

演算法中的大O理解

在描述演算法複雜度時,經常用到o 1 o n o logn o nlogn 來表示對應演算法的時間複雜度,這裡進行歸納一下它們代表的含義 這是演算法的時空複雜度的表示。不僅僅用於表示時間複雜度,也用於表示空間複雜度。o後面的括號中有乙個函式,指明某個演算法的耗時 耗空間與資料增長量之間的關係。其中的...

關於大O法的幾點解釋

大o表示法指出演算法有多快。例如,假設列表包含n個元素。簡單查詢需要檢查每個元素,因此需要執行n次操作。使用大o表示法,這個執行時間為o n 主要單位不是秒啊,大o表示法值得並非以秒為單位的速度,而是運算元,操作了幾次。它指出了演算法執行時間的增速。大o表示法指出的是最槽情況下的執行時間。如果你用簡...