The O(1) constraint is what makes this annoying.
Design an LFU cache using a combination of a hash map for O(1) key lookup and a frequency-based doubly linked list structure to track usage. Each frequency bucket contains a doubly linked list of nodes (keys) in recency order, and a min_freq pointer tracks the lowest frequency for O(1) eviction. Implement get and put by updating node frequencies and moving nodes between buckets in constant time.
Pro tip: Emphasize that the design achieves O(1) by using a min_freq pointer and that tie-breaking by recency is naturally handled by maintaining order within each frequency list. Also, mention edge cases like updating an existing key and handling capacity constraints.
Confirm that both get and put must be O(1) average time, and that eviction removes the least frequently used entry, with ties broken by least recently used. Discuss assumptions like positive capacity and integer keys/values.
Use a hash map (key -> node) for O(1) access. Maintain a doubly linked list of frequency buckets, each containing a doubly linked list of nodes with that frequency, ordered by recency. Track min_freq for O(1) eviction.
Each node stores key, value, frequency, and pointers to prev/next in its frequency list. Each frequency bucket stores its frequency value and pointers to the head/tail of its node list, plus prev/next bucket pointers.
For get: if key exists, increment its frequency, move it to the appropriate bucket (creating if needed), update min_freq if necessary, and return value. For put: if key exists, update value and increment frequency; else, if at capacity, evict from min_freq bucket's tail (LRU), then insert new node with frequency 1.
Argue that all operations are O(1) average due to hash map lookups and constant-time list manipulations. Discuss edge cases: capacity 0, updating existing key, and when min_freq bucket becomes empty.
AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.