146. LRU 缓存

请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。

实现 LRUCache 类:

  • LRUCache(int capacity)正整数 作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1
  • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

函数 getput 必须以 O(1) 的平均时间复杂度运行。

示例:

复制代码
输入
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出
[null, null, null, 1, null, -1, null, -1, 3, 4]

解释
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1);    // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2);    // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1);    // 返回 -1 (未找到)
lRUCache.get(3);    // 返回 3
lRUCache.get(4);    // 返回 4

提示:

  • 1 <= capacity <= 3000
  • 0 <= key <= 10000
  • 0 <= value <= 105
  • 最多调用 2 * 105getput

class Node

{

public:

int value;

Node*pre;

Node*next;

Node(int v)

{

pre = nullptr;

next = nullptr;

value = v;

}

};

class LRUCache {

public:

LRUCache(int capacity) {

size = capacity;

}

private:

map<int, int>m;

int size;

map<int, Node*>m_l;

Node*cur = nullptr;

Node*head = nullptr;

int curSize = 0;

public:

Node* insertNode(int key)

{

Node* node = new Node(key);

if (cur == NULL)

{

head = node;

cur = node;

curSize++;

return node;

}

cur->next = node;

node->pre = cur;

cur = cur->next;

curSize++;

return node;

}

void deleteNode(Node*node)

{

if (nullptr != node->pre && nullptr != node->next)

{

node->pre->next = node->next;

node->next->pre = node->pre;

delete node;

node = nullptr;

curSize--;

return;

}

if (nullptr == node->pre && nullptr == node->next)

{

delete node;

node = nullptr;

cur = nullptr;

curSize--;

return;

}

//delete head

if (nullptr == node->pre)

{

head = node->next;

node->next->pre = nullptr;

delete node;

node = nullptr;

curSize--;

return;

}

//delete tail

if (nullptr == node->next)

{

node->pre->next = nullptr;

cur = node->pre;

delete node;

node = nullptr;

curSize--;

return;

}

}

//delete head

void deleteHead()

{

if (nullptr == head)

{

return;

}

if (nullptr == head->next)

{

curSize--;

delete head;

head = nullptr;

cur = nullptr;

return;

}

curSize--;

Node*tmp = head->next;

delete head;

tmp->pre = nullptr;

head = tmp;

}

public:

int get(int key) {

if (m.count(key))

{

Node *node = m_l[key];

deleteNode(node);

auto pos1 = m_l.find(key);

m_l.erase(pos1);

m_l[key] = insertNode(key);

return m[key];

}

else

{

return -1;

}

}

void put(int key, int value) {

if (m.count(key))

{

m[key] = value;

Node *node = m_l[key];

deleteNode(node);

auto pos1 = m_l.find(key);

m_l.erase(pos1);

m_l[key] = insertNode(key);

return;

}

if (curSize == size)

{

int tmp = head->value;

Node *node = m_l[tmp];

auto pos = m.find(tmp);

m.erase(pos);

deleteHead();

auto pos1 = m_l.find(tmp);

m_l.erase(pos1);

}

m[key] = value;

Node *node = m_l[key];

m_l[key] = insertNode(key);

}

};

相关推荐
不当菜虚困9 分钟前
JAVA设计模式——(四)门面模式
java·开发语言·设计模式
m0Java门徒17 分钟前
面向对象编程核心:封装、继承、多态与 static 关键字深度解析
java·运维·开发语言·intellij-idea·idea
无心水43 分钟前
【Java面试笔记:基础】8.对比Vector、ArrayList、LinkedList有何区别?
java·笔记·面试·vector·arraylist·linkedlist
ApeAssistant1 小时前
Spring + 设计模式 (十四) 行为型 - 观察者模式
spring·设计模式
创码小奇客1 小时前
MongoDB 时间序列:解锁数据时光机的终极指南
java·mongodb·trae
黯_森1 小时前
Java面向对象
java·后端
代码小侦探1 小时前
Java中以Maven方式引入Oracle JDBC Driver依赖的详解
java·oracle·maven
不畏惧的少年1 小时前
AQS的底层实现原理
java
ApeAssistant1 小时前
Spring + 设计模式 (十三) 行为型 - 策略模式
spring·设计模式
斜月1 小时前
Springboot wechatpay-java 微信支付实践
spring boot·后端