0
点赞
收藏
分享

微信扫一扫

LeetCode 146. LRU 缓存机制

LeetCode 146. LRU 缓存机制_edn

 

 LeetCode 146. LRU 缓存机制_edn_02

 

 LeetCode 146. LRU 缓存机制_时间复杂度_03

 

思路

哈希表 + 双向链表。在面试中,面试官一般会期望读者能够自己实现一个简单的双向链表,而不是使用语言自带的、封装好的数据结构。  LeetCode 146. LRU 缓存机制_双向链表_04

方法一:哈希表 + C++自带的双向链表 list

1 struct Node {
2 int key;
3 int value;
4 Node(){}
5 Node(int _key,int _value): key(_key), value(_value){}
6 };
7
8 class LRUCache {
9 private:
10 int capacity;
11 list<Node*> cache;
12 unordered_map<int, list<Node*>::iterator> mp;
13 public:
14 LRUCache(int capacity) {
15 this->capacity = capacity;
16 }
17
18 int get(int key) {
19 if(mp.find(key) != mp.end()) {
20 //将其更新到队头
21 Node* node = *(mp[key]);
22 cache.erase(mp[key]);
23 cache.push_front(node);
24 mp[key] = cache.begin();
25
26 //返回对应的值
27 return node->value;
28 } else {
29 return -1;
30 }
31 }
32
33 void put(int key, int value) {
34 if(mp.find(key) != mp.end()) {
35 Node* node = *(mp[key]);
36 cache.erase(mp[key]);
37 node->value = value;
38 cache.push_front(node);
39 mp[key] = cache.begin();
40 } else {
41 Node* node = new Node(key, value);
42 cache.push_front(node);
43 mp[key] = cache.begin();
44 if(cache.size() > capacity) {
45 mp.erase(cache.back()->key);
46 cache.pop_back();
47 }
48 }
49 }
50 };
51
52 /**
53 * Your LRUCache object will be instantiated and called as such:
54 * LRUCache* obj = new LRUCache(capacity);
55 * int param_1 = obj->get(key);
56 * obj->put(key,value);
57 */

复杂度分析

时间复杂度:get和put都是O(1)。

 

方法二:哈希表 + 自己实现的简单双向链表

 LeetCode 146. LRU 缓存机制_edn_05

1 struct DLinkedNode {
2 int key, value;
3 DLinkedNode* prev;
4 DLinkedNode* next;
5 DLinkedNode(): key(0), value(0), prev(nullptr), next(nullptr) {}
6 DLinkedNode(int _key, int _value): key(_key), value(_value), prev(nullptr), next(nullptr) {}
7 };
8
9 class LRUCache {
10 private:
11 unordered_map<int, DLinkedNode*> cache;
12 DLinkedNode* head;
13 DLinkedNode* tail;
14 int size;
15 int capacity;
16
17 public:
18 LRUCache(int _capacity): capacity(_capacity), size(0) {
19 // 使用伪头部和伪尾部节点
20 head = new DLinkedNode();
21 tail = new DLinkedNode();
22 head->next = tail;
23 tail->prev = head;
24 }
25
26 int get(int key) {
27 if (!cache.count(key)) {
28 return -1;
29 }
30 // 如果 key 存在,先通过哈希表定位,再移到头部
31 DLinkedNode* node = cache[key];
32 moveToHead(node);
33 return node->value;
34 }
35
36 void put(int key, int value) {
37 if (!cache.count(key)) {
38 // 如果 key 不存在,创建一个新的节点
39 DLinkedNode* node = new DLinkedNode(key, value);
40 // 添加进哈希表
41 cache[key] = node;
42 // 添加至双向链表的头部
43 addToHead(node);
44 ++size;
45 if (size > capacity) {
46 // 如果超出容量,删除双向链表的尾部节点
47 DLinkedNode* removed = removeTail();
48 // 删除哈希表中对应的项
49 cache.erase(removed->key);
50 // 防止内存泄漏
51 delete removed;
52 --size;
53 }
54 }
55 else {
56 // 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部
57 DLinkedNode* node = cache[key];
58 node->value = value;
59 moveToHead(node);
60 }
61 }
62
63 void addToHead(DLinkedNode* node) {
64 node->prev = head;
65 node->next = head->next;
66 head->next->prev = node;
67 head->next = node;
68 }
69
70 void removeNode(DLinkedNode* node) {
71 node->prev->next = node->next;
72 node->next->prev = node->prev;
73 }
74
75 void moveToHead(DLinkedNode* node) {
76 removeNode(node);
77 addToHead(node);
78 }
79
80 DLinkedNode* removeTail() {
81 DLinkedNode* node = tail->prev;
82 removeNode(node);
83 return node;
84 }
85 };

 

复杂度分析

时间复杂度:对于 put 和 get 都是 O(1)。

空间复杂度:O(capacity),因为哈希表和双向链表最多存储 capacity + 1个元素。

 


举报

相关推荐

0 条评论