Internally, a list is represented as an array; the largest costs come from growing beyond the current allocation size (because everything must move), or from inserting or deleting somewhere near the beginning (because everything after that must move). If you need to add/remove at both ends, consider using a collections.deque instead.
Operation |
Average Case |
|
| Copy | O(n) |
O(n) |
| Append[1] | O(1) |
O(1) |
| Insert | O(n) |
O(n) |
| Get Item | O(1) |
O(1) |
| Set Item | O(1) |
O(1) |
| Delete Item | O(n) |
O(n) |
| Iteration | O(n) |
O(n) |
| Get Slice | O(k) |
O(k) |
| Del Slice | O(n) |
O(n) |
| Set Slice | O(k+n) |
O(k+n) |
| Extend[1] | O(k) |
O(k) |
| Sort | O(n log n) |
O(n log n) |
| Multiply | O(nk) |
O(nk) |
| x in s | O(n) |
|
| min(s), max(s) | O(n) |
|
| Get Length | O(1) |
O(1) |
collections.deque
Operation |
Average Case |
Amortized Worst Case |
| Copy | 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
Operation |
Average case |
Worst Case |
| x in s | O(1) |
O(n) |
| Union s|t | ||
| Intersection s&t | O(min(len(s), len(t)) |
O(len(s) * len(t)) |
| Difference s-t | O(len(s)) |
|
| s.difference_update(t) | O(len(t)) |
|
| Symmetric Difference s^t | O(len(s)) |
O(len(s) * len(t)) |
| s.symmetric_difference_update(t) | O(len(t)) |
O(len(t) * len(s)) |
As seen in the source code the complexities for set difference s-t or s.difference(t) (set_difference()) and in-place set difference s.difference_update(t) (set_difference_update_internal()) are different! The first one is O(len(s)) (for every element in s add it to the new set, if not in t). The second one is O(len(t)) (for every element in t remove it from s). So care must be taken as to which is preferred, depending on which one is the longest set and whether a new set is needed.
dict
Note that there is a fast-path for dicts that (in practice) only deal with str keys; this doesn't affect the algorithmic complexity, but it can significantly affect the constant factors: how quickly a typical program finishes.
Operation |
Average Case |
Amortized Worst Case |
| Copy[2] | O(n) |
O(n) |
| Get Item | O(1) |
O(n) |
| Set Item[1] | O(1) |
O(n) |
| Delete Item | O(1) |
O(n) |
| Iteration[2] | O(n) |
O(n) |