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.