题目 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
实现 LRUCache
类:
LRUCache(int capacity)
以 正整数 作为容量 capacity
初始化 LRU 缓存
int get(int key)
如果关键字 key
存在于缓存中,则返回关键字的值,否则返回 -1
。
void put(int key, int value)
如果关键字 key
已经存在,则变更其数据值 value
;如果不存在,则向缓存中插入该组 key-value
。如果插入操作导致关键字数量超过 capacity
,则应该 逐出 最久未使用的关键字。
函数 get
和 put
必须以 O(1)
的平均时间复杂度运行。
分析 为了满足平均$O(1)$的时间复杂度,采用哈希表+双链表的方式实现。其中哈希表用来查找指定的键,而双链表则用来维护访问时间,将最近访问过的值放在链表头,最久未使用的值放在队尾。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 class LRUCache {public : LRUCache (int cap): capacity (cap), size (0 ) { head = new DLinkedNode (); tail = new DLinkedNode (); head->next = tail; tail->prev = head; } int get (int key) { if (cache.find (key) == cache.end ()) return -1 ; auto node = cache[key]; move2head (node); return node->val; } void put (int key, int value) { if (cache.find (key) != cache.end ()) { auto node = cache[key]; node->val = value; move2head (node); } else { if (size == capacity) { cache.erase (tail->prev->key); tail->prev->val = value; tail->prev->key = key; cache.emplace (key, tail->prev); move2head (tail->prev); } else { ++size; auto node = new DLinkedNode (key, value); add2head (node); cache.emplace (key, node); } } } ~LRUCache () { delete head; delete tail; }private : struct DLinkedNode { int key, val; DLinkedNode *prev; DLinkedNode *next; DLinkedNode (): key (0 ), val (0 ), prev (nullptr ), next (nullptr ) {} DLinkedNode (int k, int v): key (k), val (v), prev (nullptr ), next (nullptr ) {} }; void add2head (DLinkedNode *node) { node->next = head->next; head->next->prev = node; head->next = node; node->prev = head; } void removeNode (DLinkedNode *node) { node->prev->next = node->next; node->next->prev = node->prev; } void move2head (DLinkedNode *node) { removeNode (node); add2head (node); } unordered_map<int , DLinkedNode*> cache; DLinkedNode *head; DLinkedNode *tail; int capacity; int size; };