当前位置:网站首页>Leetcode (146) - LRU cache
Leetcode (146) - LRU cache
2022-06-24 20:33:00 【SmileGuy17】
Leetcode(146)——LRU cache
subject
Please design and implement a meeting LRU ( Recently at least use ) cache Constrained data structure .
Realization LRUCache class :
- LRUCache(int capacity) With Positive integer As capacity capacity initialization LRU cache
- int get(int key) If the keyword key In the cache , The value of the keyword is returned , Otherwise return to -1 .
- void put(int key, int value) If the keyword key Already exist , Change its data value value ; If it doesn't exist , Then insert the group into the cache key-value . If the insert operation causes the number of keywords to exceed capacity , Should be Eviction The longest unused keyword .
function get and put Must be O ( 1 ) O(1) O(1) The average time complexity of running .
Example :
Input
[“LRUCache”, “put”, “put”, “get”, “put”, “get”, “put”, “get”, “get”, “get”]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
Output
[null, null, null, 1, null, -1, null, -1, 3, 4]
explain
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // The cache is {1=1}
lRUCache.put(2, 2); // The cache is {1=1, 2=2}
lRUCache.get(1); // return 1
lRUCache.put(3, 3); // This operation causes the keyword to 2 To void , The cache is {1=1, 3=3}
lRUCache.get(2); // return -1 ( Not found )
lRUCache.put(4, 4); // This operation causes the keyword to 1 To void , The cache is {4=4, 3=3}
lRUCache.get(1); // return -1 ( Not found )
lRUCache.get(3); // return 3
lRUCache.get(4); // return 4
Tips :
- 1 1 1 <= capacity <= 3000 3000 3000
- 0 0 0 <= key <= 10000 10000 10000
- 0 0 0 <= value <= 1 0 5 10^5 105
- Call at most 2 ∗ 1 0 5 2 * 10^5 2∗105 Time get and put
Answer key
Method 1 : Hashtable + Double linked list
Ideas
LRU The cache mechanism can be realized by hash table supplemented by bidirectional linked list , We use a hash table and a two-way linked list to maintain all key value pairs in the cache .
- The bidirectional list stores these key value pairs in the order they are used , The key value pair near the head is the most recently used , The key value pairs near the tail are the most unused .
- A hash table is a common hash map (HashMap), The key of the cached data is mapped to its position in the bidirectional linked list .
Since then , We first use a hash table for positioning , Find the location of the cache item in the bidirectional linked list , Then move it to the head of the bidirectional list , Can be in O ( 1 ) O(1) O(1) In time to complete get perhaps put operation . The specific method is as follows :
- about get operation , First judgement key Whether there is :
- If key non-existent , Then return to − 1 -1 −1;
- If key There is , be key The corresponding node is the most recently used node . Locate the position of the node in the bidirectional linked list through the hash table , And move it to the head of the two-way linked list , Finally, the value of the node is returned .
- about put operation , First judgement key Whether there is :
- If key non-existent , Use key and value Create a new node , Add the node to the head of the double linked list , And will key And the node is added to the hash table . Then judge whether the number of nodes in the two-way linked list exceeds the capacity , If the capacity is exceeded , Delete the tail node of the bidirectional linked list , And delete the corresponding item in the hash table ;
- If key There is , Then with get The operation is similar to , First, locate through the hash table , Then update the value of the corresponding node to value, And move the node to the head of the bidirectional linked list .
Of the above operations , The time complexity of accessing the hash table is O ( 1 ) O(1) O(1), Add a node at the head of the two-way linked list 、 The complexity of deleting nodes at the end of the two-way linked list is also O ( 1 ) O(1) O(1). And move a node to the head of the two-way linked list , Can be divided into 「 Delete the node 」 and 「 Add a node at the head of the two-way linked list 」 Two step operation , Can be in O ( 1 ) O(1) O(1) Within time .
Why data structures are used
- Why not use a single linked list ? Because if get When the operation accesses a node in the middle of the linked list , Using a two-way linked list, you can quickly get the addresses of the previous node and the next node , And connect them .
- Why do bi-directional linked lists store key? Because when inserting a new value , If the length of the linked list is equal to capacity , Delete the key value pairs in the hash table , At this point, you need to get the longest unused key value to call
erasefunction . - The structure of the hash table is
unordered_map<int, ListNode*>, To quickly find the corresponding key-value , At the same time, because the storage isListNode*, So you can update the linked list again .
Tips:
In the realization of bidirectional linked list , Use one Pseudo head (dummy head) and Pseudo tail (dummy tail) Mark the boundaries , In this way, there is no need to check whether adjacent nodes exist when adding or deleting nodes .

Code implementation
My own :
class LRUCache {
// Bidirectional linked list storage usage
typedef struct dataUse{
// The two-way linked list is stored in a group key-value, Because in excess of capacity To delete hashmap in key-value pair when .
// Must pass Node Inside key To delete ,hashmap Unable to get value To delete
int key;
int value;
// When get When you need to access the element whose usage is in the middle , Its previous and subsequent elements are required to facilitate reconnection
struct dataUse *next;
struct dataUse *last;
dataUse():key(-1), value(-1), next(nullptr), last(nullptr){
}
dataUse(int k, int v, struct dataUse *nextone, struct dataUse *lastone):
key(k), value(v), next(nextone), last(lastone){
}
}DU;
// The hash table stores its corresponding address in the linked list
unordered_map<int, DU*> cache;
DU *h, *t; // Head and tail , among h->next Indicates the latest unused keyword
int maxsize;
void movetoT(DU *p){
p->last->next = p->next;
p->next->last = p->last;
p->last = t->last;
p->next = t;
t->last->next = p;
t->last = p;
}
void addtoT(int key, int value){
t->last->next = new DU(key, value, t, t->last);
t->last = t->last->next;
}
public:
LRUCache(int capacity):h(new DU), t(new DU), maxsize(capacity){
h->next = t;
t->last = h;
}
int get(int key) {
if(cache.count(key) == 0) return -1;
else{
if(t->last != cache[key]) movetoT(cache[key]);
return cache[key]->value;
}
}
void put(int key, int value) {
if(cache.count(key) == 0){
if(cache.size() == maxsize){
cache.erase(h->next->key); // Delete the key pairs in the hash table that have not been used for too long
cache.emplace(key, h->next);
cache[key]->key = key;
cache[key]->value = value;
movetoT(cache[key]);
}else{
addtoT(key, value);
cache.emplace(key, t->last);
}
}else{
if(t->last != cache[key]) movetoT(cache[key]);
cache[key]->value = value;
}
}
};
/** * Your LRUCache object will be instantiated and called as such: * LRUCache* obj = new LRUCache(capacity); * int param_1 = obj->get(key); * obj->put(key,value); */
Leetcode Official explanation :
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) {
// Using pseudo head and pseudo tail nodes
head = new DLinkedNode();
tail = new DLinkedNode();
head->next = tail;
tail->prev = head;
}
int get(int key) {
if (!cache.count(key)) {
return -1;
}
// If key There is , First, locate through the hash table , And then to the head
DLinkedNode* node = cache[key];
moveToHead(node);
return node->value;
}
void put(int key, int value) {
if (!cache.count(key)) {
// If key non-existent , Create a new node
DLinkedNode* node = new DLinkedNode(key, value);
// Add to hash table
cache[key] = node;
// Add to the head of the bidirectional list
addToHead(node);
++size;
if (size > capacity) {
// If the capacity is exceeded , Delete the tail node of the bidirectional linked list
DLinkedNode* removed = removeTail();
// Delete the corresponding entry in the hash table
cache.erase(removed->key);
// Prevent memory leaks
delete removed;
--size;
}
}
else {
// If key There is , First, locate through the hash table , Revise value, And move to the head
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;
}
};
Netizen explanation :
struct lrunode{
int val;
int key;
lrunode* next;
lrunode* last;
};
class LRUCache {
public:
lrunode* mp[10001];
lrunode *list,*tail;
int capacity;
int size;
LRUCache(int capacity) {
for(int i=0;i<10001;++i)mp[i] = nullptr;
this->capacity = capacity;
list = tail = nullptr;
size = 0;
}
int get(int key) {
if(mp[key]!=nullptr){
lrunode* t = mp[key];
used(t);
return t->val;
}
else return -1;
}
void put(int key, int value) {
if(mp[key]!=nullptr){
lrunode* t = mp[key];
t->val = value;
used(t);
}else{
lrunode* node = new lrunode;
node->key = key;
node->val = value;
mp[key] = node;
push_front(node);
if(size<capacity){
size++;
}else{
pop_back();
}
}
}
void used(lrunode* t){
if(t==list)return;
if(t->last)t->last->next = t->next;
if(t->next)t->next->last = t->last;
else tail = t->last;
t->last = nullptr;
t->next = list;
if(list)list->last = t;
list = t;
if(tail == nullptr)tail = t;
}
void push_front(lrunode* node){
node->last = nullptr;
node->next = list;
if(list)list->last = node;
list = node;
if(tail == nullptr)tail = node;
}
void pop_back(){
lrunode* t = tail;
if(list == tail){
list = tail = nullptr;
}else{
tail = tail->last;
tail->next = nullptr;
}
mp[t->key] = nullptr;
delete t;
}
};
Complexity analysis
Time complexity : about put and get All are O ( 1 ) O(1) O(1).
Spatial complexity : O ( c a p a c i t y ) O(capacity) O(capacity), Because hash tables and bidirectional linked lists store the most 2 ∗ capacity + 2 2*\text{capacity} + 2 2∗capacity+2 Elements .
边栏推荐
- Sequence stack version 1.0
- Using dynamic time warping (DTW) to solve the similarity measurement of time series and the similarity identification analysis of pollution concentration in upstream and downstream rivers
- 基于QT+MySQL的相机租赁管理系统
- 顺序栈遍历二叉树
- Berkeley, MIT, Cambridge, deepmind et d'autres grandes conférences en ligne: vers une IA sûre, fiable et contrôlable
- VMware virtual machine setting static IP
- Otaku can't save yuan universe
- Q1: error in JMeter filename must not be null or empty
- Openvino2022 dev tools installation and use
- [suggested collection] time series prediction application and paper summary
猜你喜欢

The latest simulated question bank and answers of the eight members (Electrical constructors) of Sichuan architecture in 2022

使用gorm查询数据库时reflect: reflect.flag.mustBeAssignable using unaddressable value

Camera rental management system based on qt+mysql

VMware virtual machine setting static IP

红象云腾完成与龙蜥操作系统兼容适配,产品运行稳定

苹果、微软、谷歌不再掐架,今年要合力干一件大事

Bytebase rejoint la communauté de base de données open source d'alicloud polardb

Bean lifecycle flowchart

Behind Tiantian Jianbao storm: tens of millions in arrears, APP shutdown, and the founder's premeditated plan to run away?

Map跟object 的区别
随机推荐
Stackoverflow 年度报告 2022:开发者最喜爱的数据库是什么?
Dx12 engine development course progress - where does this course go
Set up your own website (14)
It is said that Tencent officially announced the establishment of "XR" department to bet on yuanuniverse; Former CEO of Google: the United States is about to lose the chip competition. We should let T
Cooking business experience of young people: bloggers are busy selling classes and bringing goods, and the organization earns millions a month
2022年最新四川建筑八大员(电气施工员)模拟题库及答案
CVPR 2022缅怀孙剑!同济、阿里获最佳学生论文奖,何恺明入围
【CANN文档速递05期】一文让您了解什么是算子
Bytebase joins Alibaba cloud polardb open source database community
首个大众可用PyTorch版AlphaFold2复现,哥大开源OpenFold,star量破千
用手机摄像头就能捕捉指纹?!准确度堪比签字画押,专家:你们在加剧歧视
unity实战之lol技能释放范围
Apple, Microsoft and Google will no longer fight each other. They will work together to do a big thing this year
Bytebase rejoint la communauté de base de données open source d'alicloud polardb
Compressed list of redis data structures
伯克利、MIT、劍橋、DeepMind等業內大佬線上講座:邁向安全可靠可控的AI
The largest DPU manufacturer in history (Part 1)
Two fellow countrymen from Hunan have jointly launched a 10 billion yuan IPO
Behind Tiantian Jianbao storm: tens of millions in arrears, APP shutdown, and the founder's premeditated plan to run away?
Uninstall tool v3.5.10.5670 single file portable official version