一、题目
请你设计并实现一个满足 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) 的平均时间复杂度运行。
Leetcode:https://leetcode.cn/problems/lru-cache
二、分析
本题使用双向链表+哈希表的方式,可以完成如上的要求。
当 get 的时候,我们从哈希表中查找,如果找不到,直接返回 -1。如果找到了,将此节点从双向链表中移动到最前端,并返回
当 put 的时候,先从哈希表中查找,如果找到了,则更改值。如果找不到,创建节点,并将其插入到哈希表,然后放在双向链表的前端。最后检测双向链表的容量,容量超了,就删除尾节点。
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
| #include <unordered_map>
struct DLinkNode { int key{0}; int val{0}; DLinkNode* prev{nullptr}; DLinkNode* next{nullptr};
DLinkNode() = default; DLinkNode(int k, int v) : key(k), val(v), prev(nullptr), next(nullptr) {} };
class LRUCache { public: explicit LRUCache(int capacity) : size_(0), capacity_(capacity) { head_ = new DLinkNode(); tail_ = new DLinkNode(); head_->next = tail_; tail_->prev = head_; }
int get(int key) { auto iter = mp_.find(key); if (iter == mp_.end()) { return -1; } else { delete_node(iter->second); add_head(iter->second); return iter->second->val; } }
void put(int key, int value) { // 存在的情况下 auto iter = mp_.find(key); if (iter != mp_.end()) { iter->second->val = value; delete_node(iter->second); add_head(iter->second); } else { // 不存在的情况 DLinkNode* node = new DLinkNode(key, value); mp_[key] = node; add_head(node); size_++; if (size_ > capacity_) { DLinkNode* node = remove_tail(); mp_.erase(node->key); delete node; size_--; } } }
private: void delete_node(DLinkNode* node) { node->prev->next = node->next; node->next->prev = node->prev; }
void add_head(DLinkNode* node) { node->prev = head_; node->next = head_->next; head_->next = node; node->next->prev = node; }
DLinkNode* remove_tail() { DLinkNode* node = tail_->prev; delete_node(node); return node; }
private: int size_{0}; int capacity_{0}; DLinkNode* head_{nullptr}; DLinkNode* tail_{nullptr}; std::unordered_map<int, DLinkNode*> mp_; };
|