The insight: use a hash map that stores pointers to list nodes.
class LRUCache:
capacity: integer
map: HashMap<key, DListNode>
head: DListNode # dummy
tail: DListNode # dummy
For get(key):
Look up node in hash map—
Move node to front of list (most recently used)—
Return node's value
For put(key, value):
If key exists, update value and move to front
If new key and at capacity, remove node at back (LRU), delete from map
Create new node, add to front, add to map
Every operation is .