定義:python
T(N) = O(f(N))
T(N) = Ω(f(N))
T(N) = θ(h(N))
當且僅當 T(N) = O(h(N))
且 T(N) = Ω(h(N))
T(N) = O(p(N))
且 T(N) != θ(p(N))
, 則 T(N) = o(p(N))
法則:算法
若 T<sub>1</sub>(N) = O(f(N)) 且 T<sub>2</sub>(N)=O(g(N)),則:dom
a. T<sub>1</sub>(N) + T<sub>2</sub>(N) = max(O(f(N)), O(g(N))) b. T<sub>1</sub>(N) * T<sub>2</sub>(N) = O(f(N) * g(N))
若 T(N) 是一個 k 次多項式,則 T(N) = Θ(N<sup>k</sup>)函數
對任意常數 k,log<sup>k</sup>N = O(N)測試
注意:優化
能夠分段讀入數據並處理問題的算法稱爲 online algrithm
,與之相對,在運算開始時就須要讀入所有數據作運算的算法稱爲 offline algrithm
。僅須要常量內存空間並以線性時間運行的算法幾乎是完美的算法。以下例最大子序列問題:ui
lang:python data = list(range(-10, 10)) random.shuffle(data) # 算法 def foo(data): this_sum = max_sum = 0 for i in data: this_sum += i if this_sum < 0: this_sum = 0 elif this_sum > max_sum: max_sum = this_sum return max_sum
若是一個算法用常數時間(O(1) )將問題的大小削減爲其一部分(一般是 1/2),那麼該算法就是 O(logN)。this
若是一個算法能夠用常數時間把問題減少一個常數,那麼他就是 O(N) 的。code
對數複雜度的一個典型例子是:二分法查找 (binary search)排序
def bin_search(numbers, x): """假設 numbers 已排序""" start = 0 end = len(numbers) - 1 while start < end: middle = (start + end) / 2 if numbers[middle] < x: start = middle + 1 elif numbers[middle] > x: end = middle - 1 else: return middle return -1
計算最大公因數:
def gcd(a, b): while b > 0: a = a % b a, b = b, a return a
定理:
若 M > N, 則 M mod N < M/2
推得:gcd 函數的時間複雜度是 O(log N) 的
優化算法的一個原則是:不要作重複的運算。
所以對於冪運算 x<sup>n</sup>,相較於進行 n-1 次乘法,下面的算法效率更高:
def pow(x, n): if n == 0: return 1 if n == 1: return n if n % 2 == 0: return pow(x * x, n / 2) else: return x * pow(x * x, (n-1) / 2)
python 中能夠用 timeit.timeit 函數方便的檢驗算法時間
timeit(stmt='pass', setup='pass', timer=<built-in function perf_counter>, number=1000000, globals=None)
其中:
* stmt statement 是一個字符串表達式 * setup 是一個執行前置語句,如 import * globals 是一個字典,存放你要使用的全局變量
如,咱們要測試 gcd 函數,則
import timeit timeit.timeit('gcd(15, 234)', globals={'gcd': gcd})