LeetCode 164. LRU 缓存

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 ,则应该 逐出 最久未使用的关键字。
    函数 get put必须以 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. 首先,函数 get putO(1) 的平均时间复杂度运行,那么就要使用到hash table进行查询操作。
  • hash table 中存放什么内容呢?其中key必然是我们执行查询的key,那么value存放什么呢?因为涉及到时间复杂度为O(1)的驱逐操作,我们考虑使用链表进行维护。你可以将此链表想象为特殊的优先队列。链表中,元素越靠前,那么它就是最近使用的。
  1. 对于get操作,首先判断key是否存在,不存在就返回-1。如果key存在,那么我们返回元素value
  2. 对于put操作,首先判断key是否存在,不存在我们需要构造元素然后将元素插入到链表头部,并且需要维护哈希表。如果key存在,那么我们需要将元素插入到链表头部,并更新哈希表。

C++ 代码

cpp 复制代码
struct DLinkNode {
    int key, value;
    DLinkNode* prev, * next;
    DLinkNode()
        : key(0), value(0), prev(nullptr), next(nullptr)
    {}
    DLinkNode(int _key, int _value)
        : key(_key), value(_value), prev(nullptr), next(nullptr)
    {}
};

class LRUCache {
public:
    LRUCache(int _capacity) 
        : capacity(_capacity), size(0)
    {
        head = new DLinkNode();
        tail = new DLinkNode();
        head->next = tail;
        tail->prev = head;
    }
    
    int get(int key) {
        // if (!cache.count(key)) return -1;
        if (cache.find(key) != cache.end()) {
            DLinkNode* node = cache[key];
            move_to_head(node);
            return node->value;
        } else {
            return -1;
        }
    }
    
    void put(int key, int value) {
        if (cache.find(key) != cache.end()) {
            DLinkNode* node = cache[key];
            node->value = value;
            move_to_head(node);
        } else {
            DLinkNode* node = new DLinkNode(key, value);
            cache.insert({key, node});
            // 其他插入的方法:1. cache[key] = value;  使用索引操作符  2. cache.insert(make_pair(key, node));  使用insert member func 3. cache.empalce(key, node); 使用emplace member func
            add_to_head(node);
            ++size;
            if (size > capacity) {
                DLinkNode* removed = remove_tail();
                cache.erase(removed->key);
                delete removed;
                --size;
            }
        }
    }
private:
    unordered_map<int, DLinkNode*> cache;
    DLinkNode* head, * tail;
    int size, capacity;
    
    void add_to_head(DLinkNode* node) {
        DLinkNode* tmp = head->next;
        head->next = node;
        node->prev = head;
        node->next = tmp;
        tmp->prev = node;
    }

    DLinkNode* remove_tail() {
        DLinkNode* node = tail->prev;
        tail->prev->prev->next = tail;
        tail->prev = tail->prev->prev;
        return node;
    }

    void move_to_head(DLinkNode* node) {
        node->prev->next = node->next;
        node->next->prev = node->prev;
        add_to_head(node);
    }
};


/**
 * 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);
 */
相关推荐
江畔柳前堤6 小时前
大语言模型分布式训练:从并行策略到万卡工程的系统梳理
人工智能·分布式·深度学习·算法·目标检测·机器学习·语言模型
Forever Nore7 小时前
LeetCode 4 寻找两个正序数组的中位数 - 二分
算法·leetcode
罗西的思考9 小时前
【OpenClaw具身硬件】MiniClaw 阅读笔记---(1)基础
人工智能·算法·机器学习
蛋先生DX9 小时前
大模型参数存储格式揭秘:BF不是男朋友
深度学习·算法·llm
爱跳舞的烤冷面10 小时前
自学嵌入式第22天(数据结构——哈希)
数据结构·算法·哈希算法
猎嘤一号10 小时前
博弈论(Game Theory)的理论、算法与工程
人工智能·算法·安全·博弈论
月光船幽幽10 小时前
影子模式下保护 logits 不被修改
人工智能·python·算法
马拉AI10 小时前
腾讯开源 Agent 记忆系统,AI“换对话就忘”的问题有了新解法(附安装使用教程)
人工智能·算法·开源·科研
地平线开发者12 小时前
征程6工具链模型X86推理方式说明
算法
地平线开发者12 小时前
【征程6】校准量化中HistogramObserver解析
算法