p101 — LFU Cache — Hints
-
The trap: if you reach for
heapqorSortedDict, you’ve already conceded O(log n). Bothgetandputmust be strictly O(1). Re-read the problem; then ask: what data structure gives O(1)remove(node)given a node pointer? Answer: doubly-linked list. -
Two levels of indexing. You need to find a key fast (level 1:
dict[key, node]). When evicting, you need to find the min-frequency key fast (level 2:dict[freq, list_of_nodes]). The level-2 list must be ordered by recency so the tail is the LRU within that frequency. -
The
min_freqpointer never scans. It can only change in two ways: (a) a brand-newputsets it to1; (b) the bucket atmin_freqbecomes empty and the just-bumped node now lives atmin_freq + 1→ somin_freq += 1. Convince yourself there is no other case. -
putof an existing key is an access too. It updates the value AND counts as agetfor tie-breaking. If you forget, your eviction picks the wrong key on the next full insert. -
Edge case the autograder loves:
capacity == 0. Everyputis a no-op; everygetreturns -1. Don’t blow up on the firstput.
If stuck: see solution.py.