146.LRU缓存-图解LRU

LRU缓存是一种满足最近最少使用约束的数据结构。我们可以用一个简单的例子来理解:假设你有一摞书,最多只能放capacity本。当你需要找一本书时,如果书在摞中,就返回它的版本(即key-value);如果不在,就返回-1。当你想放入一本新书时,如果这本书已经存在,就更新它的版本号;如果不存在,就把新书放在最上面。如果书的数量超过了capacity,就把最下面那本书移出。

那么,在这个例子中,我们主要用到了哪些操作呢?又该用什么数据结构来实现呢?由于题目要求get()和put()的时间复杂度为O(1),并且需要同时存放key-value,还要删除最久未使用的元素,因此可以使用双向链表来解决。具体来说,我们主要用到了以下操作:

1.删除

将一个节点删除

2.将节点放在最前面

3.快速找出要找的节点

使用哈希表,用key与节点作映射

cpp 复制代码
class Node {
public:
    int key;
    int value;
    Node *prev;
    Node *next;
    Node(int k = 0,int v = 0):key(k),value(v){};
};

class LRUCache {
public:
    int capacity = 0;
    Node *dummy;
    unordered_map<int,Node*> key_to_node;
    //删除节点
    void remove(Node *x) {
        x->prev->next = x->next;
        x->next->prev = x->prev;
    }
    //将节点放在最前
    void push_front(Node *x) {
        x->prev = dummy;
        x->next = dummy->next;
        x->next->prev = x;
        x->prev->next = x;
    }
    //获取节点
    Node* getNode(int key) {
        auto it = key_to_node.find(key);
        if (it == key_to_node.end()) {
            return nullptr;
        }
        Node *node = key_to_node[key];
        remove(node);
        push_front(node);
        return node;
    }
  
    LRUCache(int capacity) : capacity(capacity),dummy(new Node()) {
        dummy->next = dummy;
        dummy->prev = dummy;
    }
    
    int get(int key) {
        Node *node = getNode(key);
        return node ? node->value : -1;
    }
    
    void put(int key, int value) {
        Node *node = getNode(key);
        if (node) {
            node->value = value;
            return;
        }
        key_to_node[key] = node = new Node(key,value);
        push_front(node);
        if (capacity < key_to_node.size()) {
            //最久未使用节点
            Node *back_node = dummy->prev;
            key_to_node.erase(back_node->key);
            remove(back_node);
            //释放内存
            delete back_node;
        }
    
    }
};

时间复杂度:O(1)

空间复杂度:O(min(p,capacity),p为put的次数

相关推荐
Hi李耶几秒前
【LeetCode】541.反转字符串 II
算法·leetcode·职场和发展
shylyly_3 分钟前
104.二叉树的最大深度
数据结构·算法·104.二叉树的最大深度
AI科技星13 分钟前
曲率‑挠率与 $\boldsymbol{\omega/c}$ 的关系、精算验证及其物理意义
c语言·开发语言·线性代数·算法·决策树·机器学习·ai科技星
Henry Zhu12334 分钟前
C++17 `weak_from_this` 详解:让对象安全地观察自己
c++
nvd111 小时前
ArgoCD 双层轮询深入拆解:从 redis-app.yaml 注册到缓存重建的完整链路
redis·缓存·argocd
沐籽李1 小时前
HuDiff在抗体人源化项目中的工程化落地
人工智能·算法·aidd·抗体设计
依然范特东1 小时前
强化学习笔记6--IS、PPO、TD、DQN、Actor-Critic
笔记·算法
xiaoxiangsiyan1 小时前
LNMP + Redis Sentinel 高可用架构部署手册(续)
运维·网络·数据库·redis·缓存·架构·sentinel
一次旅行3 小时前
RLHF全链路深度解析:Reward Model数学推导+PPO完整实战,对比GRPO轻量化方案
人工智能·算法·机器学习
Wang's Blog3 小时前
AI Agent白手起家29: Few Shot 提示词工程实战
人工智能·算法