data-structures · advanced · ~50 min
Combine a hash map with a doubly-linked list to get O(1) get/put with LRU eviction.
Build a least-recently-used (LRU) cache with int keys and a fixed capacity.
Implement the following API. lru_get returns the cached value or -1 if the key is absent; lru_put inserts or updates a key, evicting the least-recently-used entry when the cache is over capacity. Both get (on a hit) and put count as "using" a key.
typedef struct lru lru_t;
lru_t *lru_create(int capacity);
int lru_get(lru_t *c, int key);
void lru_put(lru_t *c, int key, int value);
void lru_destroy(lru_t *c);
capacity: maximum number of entries (capacity > 0).lru_get returns the stored value, or -1 if the key is not present.lru_put returns nothing; it may evict the least-recently-used key.lru_create(2)
lru_put(1,10); lru_put(2,20)
lru_get(1) -> 10 (1 is now most-recently used)
lru_put(3,30) (evicts key 2, the least-recently used)
lru_get(2) -> -1 (evicted)
lru_put(1,100) (update existing key)
lru_get(1) -> 100
put of an existing key updates the value without evicting.get of a missing key returns -1.LRU caches power web browsers, database buffer pools, OS page replacement, and CDNs. Implementing one teaches the rare-but-essential 'hash map of doubly-linked-list nodes' pattern.
capacity > 0; int keys and values; up to 10000 operations.
lru_get returns the value, or -1 if the key is absent.
c points to initialized lru_cache_t. Keys and values are 32-bit integers.
#include <stdlib.h>
typedef struct lru lru_t;
lru_t *lru_create(int capacity);
int lru_get(lru_t *c, int key);
void lru_put(lru_t *c, int key, int value);
void lru_destroy(lru_t *c);
Failing to update doubly-linked pointers on node detachment leading to corrupted list.
Lookup on empty cache, inserting duplicate keys, eviction when reaching capacity.
O(1) amortized per operation. O(capacity) memory.
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.