总结Python基本数据类型的时间复杂度

2,229 阅读3分钟

此篇文章总结的数据类型/数据结构包括list, set, dict, collections.deque, heap

1. List

OperationExampleComplexity ClassNotes
Indexl[i]O(1)
Storel[i] = 0O(1)
Lengthlen(l)O(1)
Appendl.append(5)O(1)
Popl.pop()O(1)等同于l.pop(-1)
Popl.pop(i)O(N)O(N-i): l.pop(0):O(N) (see above)
Containmentx in/not in sO(N)linearly searches list
Clearl.clear()O(1)类似于 l = []
Slicel[a:b]O(b-a)l[1:5]:O(l); l[:]:O(len(l)-0)=O(N)
Extendl.extend(...)O(len(...))depends only on len of extension
check ==, !=l1 == l2O(N)
Insertl[a:b] = ...O(N)
Deletedel l[i]O(N)depends on i; O(N) in worst case
Copyl.copy()O(N)等同于slice全部
Removel.remove(a)O(N)移除list中第一个a
Extreme valuemin(l)/max(l)O(N)线性搜索list
Reversel.reverse()O(N)
Iterationfor v in l:O(N)Worst: no return/break in loop
Sortl.sort()O(N Log N)key/reverse mostly doesn't change
Multiplyk*lO(k N)5*l is O(N); len(l)*l is O(N**2)
Constructionlist(...)O(len(...))depends on length of ... iterable

Tuples支持所有不改变数据结构的操作(它们具有相同的复杂度)。

2. Set

OperationExampleComplexityNotes
Lengthlen(s)O(1)
Adds.add(5)O(1)
Containmentx in/not in sO(1)compare to list/tuple - O(N)
Removes.remove(..)O(1)compare to list/tuple - O(N)
Discards.discard(..)O(1)如果元素不存在,discard不会报错,remove会报错
Pops.pop()O(1)随机pop一个元素
Clears.clear()O(1)similar to s = set()
check ==, !=s != tO(len(s))same as len(t); False in O(1) if the lengths are different
<=/<s <= tO(len(s))issubset
>=/>s >= tO(len(t))issuperset;s <= t == t >= s
UnionstO(len(s)+len(t))
Intersections & tO(min(len(s), len(t)))t不一定需要是set,当t不是set时,复杂度计算要把min换成max
Differences - tO(len(s)求差集是把在s中不在t中的元素加到新的集合里
更新为差集s.difference_update(t)O(len(t))更新为差集是把t中元素从s中移除
Symmetric Diffs ^ tO(len(s)+len(t))删除两个集合中都存在的元素
Iterationfor v in s:O(N)Worst: no return/break in loop
Copys.copy()O(N)
Constructionset(...)O(len(...))depends on length of ... iterable

相比于list和tuple,set多了很多O(1)的操作

3. dict and defaultdict

OperationExampleComplexityNotes
Indexd[k]O(1)
Stored[k] = vO(1)
Lengthlen(d)O(1)
Deletedel d[k]O(1)
get/setdefaultd.get(k)O(1)
Popd.pop(k)O(1)
Pop itemd.popitem()O(1)popped item "randomly" selected
Cleard.clear()O(1)similar to s = {} or = dict()
Viewd.keys()O(1)same for d.values()
Constructiondict(...)O(len(...))depends # (key,value) 2-tuples
Iterationfor k in d:O(N)all forms: keys, values, items; Worst: no return/break in loop

4. Collections.deque

deque (double-ended queue,双向队列)是以双向链表的形式实现的 (Well, a list of arrays rather than objects, for greater efficiency)。双向队列的两端都是可达的,但从查找队列中间的元素较为缓慢,增删元素就更慢了。

OperationExampleComplexityNotes
Appendd.append()O(1)
Appendleftd.appendleft()O(1)
Popd.pop()O(1)
Popleftd.popleft()O(1)
Extendd.extend()O(k)
Extendleftd.extendleft()O(k)
Rotated.rotate()O(k)
Removed.remove(..)O(n)

deque是线程安全的,可以同时从deque的左边和右边进行操作。 可以用deque(maxlen=n)设置deque长度,超过长度时会从另一边自动删除。

5. Heapq

OperationExampleComplexityNotes
Pushheapq.heappush(heap, item)O(logN)
Popheapq.heappop(heap)O(logN)弹出并返回堆中的最小项,保持堆不变。如果堆是空的,则引发IndexError。
Push+Popheapq.heappushpop(heap, item)O(logN)比组合调用push+pop更有效率
Heapifyheapq.heapify(x)O(logN)
Replaceheapq.heapreplace(n)O(logN)pop smallest item and push new item, 比pop+push更有效率