big O notation

大O符號是一種算法複雜度的相對錶示方式。

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

  • 相對(relative):你只能比較相同的事物。你不能把一個做算數乘法的算法和排序整數列表的算法進行比較。但是,比較2個算法所做的算術操作(一個做乘法,一個做加法)將會告訴你一些有意義的東西;
  • 表示(representation):大O(用它最簡單的形式)把算法間的比較簡化爲了一個單一變量。這個變量的選擇基於觀察或假設。例如,排序算法之間的對比通常是基於比較操作(比較2個結點來決定這2個結點的相對順序)。這裏面就假設了比較操作的計算開銷很大。但是,如果比較操作的計算開銷不大,而交換操作的計算開銷很大,又會怎麼樣呢?這就改變了先前的比較方式;
  • 複雜度(complexity):如果排序10,000個元素花費了我1秒,那麼排序1百萬個元素會花多少時間?在這個例子裏,複雜度就是相對其他東西的度量結果。

在你閱讀了本文剩餘部分後,再回來重讀上面的文字吧。

我所能想到的大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符號是關於一個算法的最壞情況的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章