微软面试题: LeetCode 146. LRU 缓存机制 middle 出现次数:3

实现一个  LRUCache 类:使得 put 和  get 操作都达到 O(1)

 哈希表 + 双向队列

双向队列 中存储 缓存(页面)信息,使用哈希表可以实现O(1) 找到 缓存的位置,使用双向队列可以 实现O(1)

时间的从头部插入(更新刚用过的页为最新状态)和从尾部删除(淘汰最近最久未使用的页)。

直接上代码:

 1 struct Node
 2 {
 3     int key;
 4     int value;
 5     Node(int k,int v):key(k),value(v){}
 6 };
 7 class LRUCache {
 8 public:
 9     LRUCache(int capacity):buff_size(capacity) {}
10     
11     int get(int key)
12     {
13         // get 操作 缺页,直接返回 -1
14         if(hash_table.find(key) == hash_table.end())
15         {
16             return -1;
17         }
18         // 借助哈希表O(1)实现 get操作
19         int value = hash_table[key]->value;
20         // 刷新当前页为最新
21         put( key, value);
22        // Cache.splice(Cache.begin(), Cache,hash_table[key]);
23         return value;
24     }
25     
26     void put(int key, int value)
27     {
28         //未命中且Cache已满,淘汰最近最久未使用页,
29         if(hash_table.find(key) == hash_table.end() && Cache.size() == buff_size)
30         {
31             int key = Cache.back().key;
32             Cache.pop_back();//淘汰最近最久未使用页
33             hash_table.erase(key);//同时删除hash表中对应的记录
34         }
35         //命中 删除掉Cache中目标记录,此时hash表可不更新,因为该页马上就要再插入Cache
36         if(hash_table.find(key) != hash_table.end())
37         {
38             Cache.erase(hash_table[key]);
39         }
40         //将当前页面重新插入到Cache 头部,同时更新hash表记录当前页最新位置
41         Node node(key,value);
42         Cache.push_front(node);
43         hash_table[key] = Cache.begin();
44         return;
45     }
46 private:
47     int buff_size;
48     list<Node> Cache;
49     unordered_map<int,list<Node>::iterator> hash_table;
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  */

使用 list 的splice 函数 ,可以提高效率 ,代码如下:

 1 struct Node
 2 {
 3     int key;
 4     int value;
 5     Node(int k,int v):key(k),value(v){}
 6 };
 7 class LRUCache {
 8 public:
 9     LRUCache(int capacity):buff_size(capacity) {}
10     
11     int get(int key)
12     {
13         // get 操作 缺页,直接返回 -1
14         if(hash_table.find(key) == hash_table.end())
15         {
16             return -1;
17         }
18         // 借助哈希表O(1)实现 get操作
19         int value = hash_table[key]->value;
20         // 刷新当前页为最新
21         //put( key, value);
22           Cache.splice(Cache.begin(), Cache,hash_table[key]);
23         return value;
24     }
25     
26     void put(int key, int value)
27     {
28         //命中 删除掉Cache中目标记录,此时hash表可不更新,因为该页马上就要再插入Cache
29         if(hash_table.find(key) != hash_table.end())
30         {
31             hash_table[key]->value = value;
32             return Cache.splice(Cache.begin(), Cache,hash_table[key]);
33         }
34         //将当前页面重新插入到Cache 头部,同时更新hash表记录当前页最新位置
35         Node node(key,value);
36         Cache.push_front(node);
37         hash_table[key] = Cache.begin();
38         if(Cache.size() > buff_size)
39         {
40             hash_table.erase(Cache.back().key);
41             Cache.pop_back();
42         }
43         return;
44     }
45 private:
46     int buff_size;
47     list<Node> Cache;
48     unordered_map<int,list<Node>::iterator> hash_table;
49 };
50 
51 /**
52  * Your LRUCache object will be instantiated and called as such:
53  * LRUCache* obj = new LRUCache(capacity);
54  * int param_1 = obj->get(key);
55  * obj->put(key,value);
56  */

    

原文地址:https://www.cnblogs.com/wangxf2019/p/14077357.html