前一篇介紹了快速排序,本篇將重點介紹“大O表示法”。
閱讀本文你將收獲:
- 時間復雜度的概念。
- 空間復雜度的概念。
- 大O表示法。
一個算法的優劣主要從算法的執行時間和所需要占用的存儲空間兩個方面來衡量。所對應的兩個指標分別是“時間復雜度”與“空間復雜度”。
故在正式介紹大O表示法之前,我們先來看看算法優劣的兩個指標:“時間復雜度”與“空間復雜度”。
一、時間復雜度
時間復雜度是指一個算法被執行所需要的計算工作量。它用來度量算法執行的時間長短。
時間復雜度常用大O表示法表示,且不包括這個函數的“低階項”與“首項系數”。
算法的時間復雜度實質上是一個數學函數,它定量描述了該算法的運行時間。常用大O表示法表示。
記做:T(n) = O(f(n))
二、空間復雜度
空間復雜度是指一個算法在運行過程中臨時占用存儲空間大小的量度。
空間復雜度通常也用大O表示法表示。
記做:S(n)=O(f(n))。
分析一個算法所占用的存儲空間大小需要多方面考慮。
比如,
對于遞歸算法來說,算法本身所占用的存儲單元較少,但在運行時需要申請額外的堆棧,從而需要占用較多的臨時工作單元。
對于非遞歸算法來說,算法本身所占用的存儲單元較多,而在運行時占用的臨時工作單元較少。
三、大O表示法
對于一個算法來說,時間復雜度與空間復雜度往往是互相影響的。追求較好的時間復雜度,往往空間復雜度會差一些。追求較好的空間復雜度,往往時間復雜度會差一些。
算法的時間復雜度和空間復雜度合稱為算法的復雜度。而衡量算法復雜度需要用到大O表示法。
3.1 什么是大O表示法?
定義:稱一個函數
g(n)
是O(f(n))
,當且僅當存在常數c>0
和n0>=1
時,對一切n>n0
均有|g(n)|<=c|f(n)|
成立,也稱函數g(n)
以f(n)
為界。記作g(n)=O(f(n))
。(來源360百科)
簡單來說,大O表示法就是一個由n
表示的函數(n
代表輸入量),通過不斷擴大n
的值,來漸進反應算法的復雜度。
是不是有點難理解?接下來讓我們看幾個常見實例就會了然于心。
3.2 大O表示法的幾種常見實例
下面從性能的角度,由高到低的介紹幾種大O表示法常見實例:
1) 常數級:O(1)
O(1)表示該算法的執行時間(或執行時占用空間)總是為一個常量,不論輸入的數據集是大是小。
例如:取數組第一個元素的時間復雜度:
def getFirstElement(arr):
return arr[0]
2) 對數級:O(log2n)
O(log2n)表示每次循環,所要處理的數據量減半。
例如:二分查找的時間復雜度。
def binary_search(list, item):
low = 0
high = len(list) - 1
while low <= high:
mid = (low + high) / 2
if list[mid] == item:
return mid
if list[mid] > item:
high = mid - 1
else:
low = mid + 1
return None
3) 線性級:O(n)
O(N)表示一個算法的性能會隨著輸入數據的大小變化而線性變化。
例如:簡單查找的時間復雜度。
def easy_search(list, item):
for index in range(len(list)):
if list[index] == item:
return index
return None
4) 線性對數級:O(nlog2n)
O(nlog2n)表示一個算法的性能會隨著輸入數據的大小變化而線性對數級變化。
例如:快速排序的時間復雜度。
def quickSort(arr):
if len(arr) < 2:
return arr
else:
pivot = arr[0]
less = [i for i in arr[1:] if i <= pivot]
greater = [i for i in arr[1:] if i > pivot]
return quickSort(less) + [pivot] + quickSort(greater)
5) 平方級:O(n2)
O(n2)表示一個算法的性能會隨著輸入數據的大小變化而發生平方級變化。
舉例:選擇排序的時間復雜度。(典型的兩層for循環遍歷)
def findSmallest(arr):
smallest = arr[0]
smallest_index = 0
for i in range(1, len(arr)):
if arr[i] < smallest:
smallest = arr[i]
smallest_index = i
return smallest_index
def selectionSort(arr):
newArr = []
for i in range(len(arr)):
smallest = findSmallest(arr)
newArr.append(arr.pop(smallest))
return newArr
6) 立方級:O(n3)
O(n3)表示一個算法的性能會隨著輸入數據的大小變化而發生立法級變化。
舉例:三層for循環的遍歷算法的時間復雜度。
7) k次方級:O(nk)
O(nk)表示一個算法的性能會隨著輸入數據的大小變化而發生k次方級變化。
舉例:k層for循環的遍歷算法的時間復雜度。
8) 指數級:O(2n)
O(2n)表示一個算法的性能將會隨著輸入數據的每次增加而增大兩倍。
舉例:斐波那契數列的時間復雜度。
def Fibonacci(n):
if(n>=2):
return Fibonacci(n - 1) + Fibonacci(n - 2)
else:
return n
推薦文章:
iOS UIWebView、WKWebView注入Cookie
Cookie簡介
iOS 圖標&啟動圖生成器(一)
算法小專欄:“D&C思想”與“快速排序”