1. 程式人生 > >Python內建方法的時間複雜度

Python內建方法的時間複雜度

轉載自:http://www.orangecube.net/python-time-complexity

本文翻譯自Python Wiki
本文基於GPL v2協議,轉載請保留此協議。

本頁面涵蓋了Python中若干方法的時間複雜度(或者叫“大歐”,“Big O”)。該時間複雜度的計算基於當前(譯註:至少是2011年之前)的CPython實現。其他Python的實現(包括老版本或者尚在開發的CPython實現)可能會在效能表現上有些許小小的差異,但一般不超過一個O(log n)項。

本文中,’n’代表容器中元素的數量,’k’代表引數的值,或者引數的數量。

列表(list

以完全隨機的列表考慮平均情況。

列表是以陣列(Array)實現的。最大的開銷發生在超過當前分配大小的增長,這種情況下所有元素都需要移動;或者是在起始位置附近插入或者刪除元素,這種情況下所有在該位置後面的元素都需要移動。如果你需要在一個佇列的兩端進行增刪的操作,應當使用collections.deque(雙向佇列)

操作 平均情況 最壞情況
複製 O(n) O(n)
append[注1] O(1) O(1)
插入 O(n) O(n)
取元素 O(1) O(1)
更改元素 O(1) O(1)
刪除元素 O(n) O(n)
遍歷 O(n) O(n)
取切片 O(k) O(k)
刪除切片 O(n) O(n)
更改切片 O(k+n) O(k+n)
extend[注1] O(k) O(k)
排序 O(n log n) O(n log n)
列表乘法 O(nk) O(nk)
x in s O(n)
min(s), max(s) O(n)
計算長度 O(1) O(1)

雙向佇列(collections.deque

deque (double-ended queue,雙向佇列)是以雙向連結串列的形式實現的 (Well, a list of arrays rather than objects, for greater efficiency)。雙向佇列的兩端都是可達的,但從查詢佇列中間的元素較為緩慢,增刪元素就更慢了。

操作 平均情況 最壞情況
複製 O(n) O(n)
append O(1) O(1)
appendleft O(1) O(1)
pop O(1) O(1)
popleft O(1) O(1)
extend O(k) O(k)
extendleft O(k) O(k)
rotate O(k) O(k)
remove O(n) O(n)

集合(set)

未列出的操作可參考 dict —— 二者的實現非常相似。

操作 平均情況 最壞情況
x in s O(1) O(n)
並集 s|t O(len(s)+len(t))
交集 s&t O(min(len(s), len(t)) O(len(s) * len(t))
差集 s-t O(len(s))
s.difference_update(t) O(len(t))
對稱差集 s^t O(len(s)) O(len(s) * len(t))
s.symmetric_difference_update(t) O(len(t)) O(len(t) * len(s))

由原始碼得知,求差集(s-t,或s.difference(t))運算與更新為差集(s.difference_uptate(t))運算的時間複雜度並不相同!前者是將在s中,但不在t中的元素新增到新的集合中,因此時間複雜度為O(len(s));後者是將在t中的元素從s中移除,因此時間複雜度為O(len(t))。因此,使用時請留心,根據兩個集合的大小以及是否需要新集合來選擇合適的方法。

集合的s-t運算中,並不要求t也一定是集合。只要t是可遍歷的物件即可。

字典(dict)

下列字典的平均情況基於以下假設:
1. 物件的雜湊函式足夠擼棒(robust),不會發生衝突。
2. 字典的鍵是從所有可能的鍵的集合中隨機選擇的。

小竅門:只使用字串作為字典的鍵。這麼做雖然不會影響演算法的時間複雜度,但會對常數項產生顯著的影響,這決定了你的一段程式能多快跑完。

操作 平均情況 最壞情況
複製[注2] O(n) O(n)
取元素 O(1) O(n)
更改元素[注1] O(1) O(n)
刪除元素 O(1) O(n)
遍歷[注2] O(n) O(n)

注:
[1] = These operations rely on the “Amortized” part of “Amortized Worst Case”. Individual actions may take surprisingly long, depending on the history of the container.

[2] = For these operations, the worst case n is the maximum size the container ever achieved, rather than just the current size. For example, if N objects are added to a dictionary, then N-1 are deleted, the dictionary will still be sized for N objects (at least) until another insertion is made.