codejump
HardPro challengePythonJavaScriptTypeScript

System Design — LFU Cache

System DesignCachingHash MapLinked List

lru-cache evicts what was used least recently. An LFU cache evicts what was used
least frequently, which protects hot keys from being flushed by a one-off scan.

solve(args, ops) builds new LFUCache(capacity) — args = [capacity] — and replays ops:

  • get(key) — return the value, or -1 if absent. A hit counts as one use.
  • put(key, value) — insert or update (an update counts as one use, a new key starts at

one use). Returns nothing. When the cache is full and the key is new, first evict the key
with the lowest use count; among keys with that same count, evict the **least recently
used** one. A capacity of 0 stores nothing.

Both operations must be O(1). The standard design: key → (value, count), plus
count → ordered set of keys (a Map keeps insertion order, which gives you LRU inside a
count), plus a minCount pointer that you can maintain without scanning.

Example (capacity = 2)

put(1,1) put(2,2) get(1)→1  put(3,3)   // evicts 2 (used once, key 1 was used twice)
get(2)→-1  get(3)→3  put(4,4)         // 1 and 3 both used twice: 1 is less recent → evicted
get(1)→-1  get(3)→3  get(4)→4

Sample tests

Test #1Classic example
Input: [[2],[["put",1,1],["put",2,2],["get",1],["put",3,3],["get",2],["get",3],["put",4,4],["get",1],["get",3],["get",4]]]
Output: [null,null,1,null,-1,3,null,-1,3,4]
Test #2Capacity zero
Input: [[0],[["put",0,0],["get",0]]]
Output: [null,-1]
Test #3An update counts as a use
Input: [[2],[["put",1,"a"],["put",2,"b"],["put",1,"A"],["put",3,"c"],["get",2],["get",1]]]
Output: [null,null,null,null,-1,"A"]