LeetCode刷题笔记 - 常用的Python代码
We assume python 3.11, which is the python version used in LeetCode (see doc)
Common Data Structures
List
lst = [2,4,6]
lst.append(x) # Add at end
lst.pop() # Remove from end
lst.pop(i) # Remove at index
lst.insert(i, x) # Insert at index.
# For lst=[y, z], lst.insert(1, x) results in [y, x, z]
lst.remove(x) # Remove first occurrence
lst.sort() # In-place sort
lst.reverse() # In-place reverse
sorted(lst) # Returns new sorted list
lst.index(x) # Find first index of x
Tuple
Immutable, and hashable (can be used as element in set / key in dict)
Set
s = set([2,2,2,4,6]) # the same as `s = {2, 4, 6}`
s.add(x) # Add to set, dedup
s.remove(x) # Remove elem, if not exists throw err
s.discard(x) # Remove elem, if not exists ignore
s.pop() # Randomly pop one elem
s.union(t)
s.intersection(t)
s.difference(t)
s.symmetric_difference(t)
Dictionary
d.get(k, default)
d.keys(), d.values(), d.items()
d.pop(k)
d.popitem()
d.setdefault(k, default)
Deque: collections.deque
Double-ended queue.
from collections import deque
dq = deque([2,4,6])
dq.append(x)
dq.appendleft(x)
dq.pop()
dq.popleft()
dq.rotate(n)
Heap: heapq
heapq
provides min-heap. A min-heap is a complete binary tree where every parent node <= its children.
Time complexity of useful ops:
access min elem:
O(1)
insert / remove elem:
O(log N)
create heap:
O(N)
Min-heap can be used to efficiently implement priority queue where tasks of highest priority is processed first.
nums = [(5, "task A"), (3, "task B"), (8, "task C"), (1, "task D")]
# nums is ordered after heapify
heapq.heapify(nums)
# nums is [(1, 'task D'), (3, 'task B'), (8, 'task C'), (5, 'task A')]
heapq.heappush(nums, (2, "task E"))
# nums is [(1, 'task D'), (2, 'task E'), (3, 'task B'), (8, 'task C'), (5, 'task A')]
# Peak smallest
smallest = nums[0]
# Pop smallest, re-heapify
# Elements are swapped in place to simulate ops on binary tree, so that heappop is O(log N)
smallest = heapq.heappop(nums) # (1, 'task D')
Note: Conceptually, heap is a tree. In practice, we represent it as a sorted list. For each element at index
i
,
- it’s left child is at
2*i + 1
- it’s right child is at
2*i + 2
- it’s parent is at
(i - 1) // 2
Counter collections.Counter
Counter w/ efficient top-k most common retrieval (heap-based impl).
from collections import Counter
lst = [1,1,2,3,3,3,3,4,4,5]
c = Counter(lst)
# c.most_common(k) returns top k most common elements
# in the form [(elem, freq)]
c.most_common(2) # [(3, 4), (1, 2)]
c.most_common(3) # [(3, 4), (1, 2), (4, 2)]
# Iterator
c.elements()
# <itertools.chain object at 0x7fe91b2f2a70>
# Update
c.update([1,1,1,1,1,1])
c.most_common(2) # [(1, 8), (3, 4)]
Dictionary w/ Default Value: collections.defaultdict
Just a “nice to have”, not really a substantially different data structure.
Instead of
d = dict()
# ...
if key not in d:
d[key] = []
d[key].append(10)
we can use defaultdict
and write
from collections import defaultdict
# defaultdict(default_factory)
# e.g. defaultdict(lamdba: "foobar")
d = defaultdict(list)
# ...
d[key].append(10)
Note that an item is created when you call
d[key]
If you don’t want it to be created, you can just call d.get(key)
.
Common Code Snippets
Heap with custom comparator
class Task
def __init__(self, name, prio):
self.name = name
# Smaller means higher priority
self.prio = prio
def __lt__(self, other):
return self.prio < other.prio
import heapq
heap = []
heapq.heappush(heap, Task("Do laundry", 2))
heapq.heappush(heap, Task("Write code", 1))
print(heapq.heappop(heap).name) # "Write code"