線性查找並不總是O(N)的。當要找的元素在數組末尾,那確實是O(N)。但如果它在數組開頭,1 步就能找到的話,那么技術上來說應該是O(1)。所以概括來說,線性查找的最好情況是O(1),最壞情況是O(N)。雖然大O可以用來表示給定算法的最好和最壞的情景,但若無特別說明,大O 記法一般都是指最壞情況。因此盡管線性查找有O(1)的最好情況,但大多數資料還是把它歸類為O(N)。
這種悲觀主義其實是很有用的:知道各種算法會差到什么程度,能使我們做好最壞打算,以選出最適合的算法。
在同一個有序數組里,二分查找比線性查找要快。
用大O 記法描述二分查找:它不能寫成O(1),因為二分查找的步數會隨着數據量的增長而增長。它也不能寫成O(N),因為步數比元素數量要少得多,正如之前我們看到的,包含100 個元素的數組只要7 步就能找完。
二分查找的時間復雜度介於O(1)和O(N)之間。二分查找的大O 記法是:O(log N) 讀作“O log N”。歸於此類的算法,它們的時間復雜度都叫作對數時間。
O(log N)意味着該算法當數據量翻倍時,步數加1。
3 種時間復雜度,按照效率由高到低來排序的話,會是這樣:O(1) O(log N) O(N)
O(log N)曲線的微彎,使其效率略差於O(1),卻遠勝於O(N)。
log 即是對數(logarithm)。對數是指數的反函數。
23 等於:2 × 2 × 2結果為8。log2 8 則將上述計算反過來,它意思是:要把2 乘以自身多少次,才能得到8。因為需要3次,所以,log2 8 = 3。
26 可以解釋為:2 × 2 × 2 × 2 × 2 × 2 = 64 因為2 要乘以自身6 次才得到64,所以,log2 64 = 6。
log2 8 可以表達為:將8 不斷地除以2 直到1,需要多少個2。8 / 2 / 2 / 2 = 1(注:按照從左到右的順序計算。)或者說,將8 不斷地除以2,要除多少次才能到1 呢?答案是3,所以,log2 8 = 3。
類似地,log2 64 可以解釋為:將64 除以2 多少次,才能得到1。64 / 2 / 2 / 2 / 2 / 2 / 2 = 1 因為這里有6 個2,所以,log2 64 = 6。
O(log N)指的是O(log2 N),不過為了方便就省略了2而已。O(N)代表算法處理N 個元素需要N 步。如果元素有8 個,那么這種算法就需要8 步。
O(log N)則代表算法處理N 個元素需要log2 N 步。如果有8 個元素,那么這種算法需要3 步,因為log2 8 = 3。
從另一個角度來看,如果要把8 個元素不斷地分成兩半,那么得拆分3 次才能拆到只剩1 個元素。
這正是二分查找所干的事情。它就是不斷地將數組拆成兩半,直至范圍縮小到只剩你要找的那個元素。
簡單來說,O(log N)算法的步數等於二分數據直至元素剩余1 個的次數。
每次數據量翻倍時,O(N)算法的步數也跟着翻倍,O(log N)算法卻只需加1。