PROBLEM
146. LRU 缓存机制
难度 中等
MY ANSWER
无。
BETTER SOLUTION
双向链表与哈希表实现,哈希表存储key与对应节点指针,双向列表保证删除和添加都为O(1)。双向链表使用虚拟头节点与尾节点来省略空结点判断,每当使用一个节点或增加一个节点,就把节点移到头部,满时将尾节点删除。
struct DLinkedNode { int key, value; DLinkedNode* prev; DLinkedNode* next; DLinkedNode(): key(0), value(0), prev(nullptr), next(nullptr) {} DLinkedNode(int _key, int _value): key(_key), value(_value), prev(nullptr), next(nullptr) {} };
class LRUCache { private: unordered_map<int, DLinkedNode*> cache; DLinkedNode* head; DLinkedNode* tail; int size; int capacity;
public: LRUCache(int _capacity): capacity(_capacity), size(0) { head = new DLinkedNode(); tail = new DLinkedNode(); head->next = tail; tail->prev = head; } int get(int key) { if (!cache.count(key)) { return -1; } DLinkedNode* node = cache[key]; moveToHead(node); return node->value; } void put(int key, int value) { if (!cache.count(key)) { DLinkedNode* node = new DLinkedNode(key, value); cache[key] = node; addToHead(node); ++size; if (size > capacity) { DLinkedNode* removed = removeTail(); cache.erase(removed->key); delete removed; --size; } } else { DLinkedNode* node = cache[key]; node->value = value; moveToHead(node); } }
void addToHead(DLinkedNode* node) { node->prev = head; node->next = head->next; head->next->prev = node; head->next = node; } void removeNode(DLinkedNode* node) { node->prev->next = node->next; node->next->prev = node->prev; }
void moveToHead(DLinkedNode* node) { removeNode(node); addToHead(node); }
DLinkedNode* removeTail() { DLinkedNode* node = tail->prev; removeNode(node); return node; } };
|
SUMMARY
熟悉双向链表的代码,哈希表存储指针可保证O(1)访问节点。