一個 O(log n)的例子

介紹

請考慮以下問題:

L 是一個包含 n 有符號整數的排序列表(n 足夠大),例如 [-5, -2, -1, 0, 1, 2, 4](這裡,n 的值為 7)。如果已知 L 包含整數 0,那麼如何找到 0 的索引?

天真的方法

首先想到的是隻讀取每個索引,直到找到 0。在最壞的情況下,操作次數是 n,因此複雜度為 O(n)

這適用於 n 的小值,但是有更有效的方法嗎?

二分法

考慮以下演算法(Python3):

a = 0
b = n-1
while True:
  h = (a+b)//2 ## // is the integer division, so h is an integer
  if L[h] == 0:
    return h
  elif L[h] > 0:
    b = h
  elif L[h] < 0:
    a = h

ab 是要找到 0 的索引。每次我們進入迴圈時,我們使用 ab 之間的索引,並使用它來縮小要搜尋的區域。

在最壞的情況下,我們必須等到 ab 相等。但這需要多少次操作?不是 n,因為每次我們進入迴圈時,我們將 ab 之間的距離除以 2。相反,複雜性是 O(log n)。

說明

注意:當我們寫 log 時,我們指的是二進位制對數,或者 log base 2(我們將寫入“log_2”)。由於 O(log_2 n)= O(log n)(你可以進行數學運算),我們將使用 log 而不是“log_2”。

讓我們呼叫 x 操作的數量:我們知道 1 = n /(2 ^ x)。

所以 2 ^ x = n,然後 x = log n

結論

當面對連續的劃分(無論是兩個還是任何數字)時,請記住複雜性是對數的。