牛客热题:设计LRU缓存结构

📟作者主页:慢热的陕西人

🌴专栏链接:力扣刷题日记

📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言

文章目录

牛客热题:设计LRU缓存结构

题目链接

设计LRU缓存结构_牛客题霸_牛客网 (nowcoder.com)

方法一:map+双向链表

思路

set

​ step1:查看对应的key是否已经被set过

​ step2:如果set过就将对应的节点移动到链表头,并且在哈希中改变其val的值

​ step3:如果没有set过就构建一个新的节点在哈希中创建映射,然后将新的节点插入到链表的头部

​ step4:查看缓存空间是否溢出

​ step5: 如果溢出就删除对应的链表尾部的节点,然后将哈希中的映射删除掉,并释放掉对应的节点

get

​ step1:查看是否在哈希表中出现过

​ step2:如果出现过,将其在链表中的节点移动到链表头的位置,并返回对应的val

​ step3:如果没出现过,那么直接返回-1

代码

cpp 复制代码
class Node
{
public:
    int _key;
    int _val;
    Node* _prev;
    Node* _next;
    //初始化
public:
    Node(int key, int val)
    {
        _key = key;
        _val = val;
        _prev = nullptr;
        _next = nullptr;
    }
};

class Solution {
public:
 Solution(int capacity)
 {
    size = capacity;
    head = new Node(0, 0);
    tail = new Node(0, 0);
    //将头节点和尾部节点连上
    head->_next = tail;
    tail->_prev = head;
 }
 
 int get(int key) 
 {
    if(hash.count(key))
    {
        MoveToHead(hash[key]);
        return hash[key]->_val;
    }
    else
    {
        return -1;
    } 
 }
 
 void set(int key, int value)
 {
    //1.是否已经被set过
    if(hash.count(key))
    {
        //2.将其节点移动到链表头
        MoveToHead(hash[key]);
        hash[key]->_val = value;
        cout << 2 << endl;
    }
    else 
    {
        //3.将新节点插入到链表的头部
        Node* NewNode = new Node(key, value);
        InsertToHead(NewNode);
        hash[key] = NewNode;

        //4.如果空间不够
        if(size <= 0)
        {
            //将链表尾部的节点去掉
            EraseLast();
            size++;
        }
        //5.减小空间
        size--;
    }
 }

void EraseLast()
{
    //先在哈希表中删除映射
    hash.erase(tail->_prev->_key);
    //在链表中删除
    Node* cur = tail->_prev;
    tail->_prev->_prev->_next = tail;
    tail->_prev = tail->_prev->_prev;
    delete cur;
    cur = nullptr;
}

void MoveToHead(Node* node)
{
    //已经是头部
    if(head == node->_prev)
    {
        return ;
    }
    //先将这个节点拆下来
    node->_prev->_next = node->_next;
    node->_next->_prev = node->_prev;
    
    InsertToHead(node);
}

void InsertToHead(Node* node)
{
    node->_next = head->_next;
    node->_prev = head;
    head->_next->_prev = node;
    head->_next = node;
}

private:
    int size;
    Node* head;
    Node* tail;
    map<int, Node*> hash;
};

复杂度

时间复杂度:O(1),不论是set操作还是get操作均在O(1)的时间复杂度

空间复杂度:O(N), 利用到了长度等于size+2的链表长度和对应的map

相关推荐
難釋懷7 小时前
Nginx内存缓存
nginx·缓存·junit
飞翔的馒7 小时前
浏览器缓存之【结构化数据库与缓存】: IndexedDB、Cache storage 和 Storage buckets
数据库·缓存
怪兽学LLM10 小时前
AI 应用中的高并发处理:从限流、异步到缓存与队列
人工智能·缓存
喜欢的名字被抢了13 小时前
长会话状态治理:当Redis失忆后,系统如何自己找回忆
数据库·redis·缓存
Alan_6911 天前
商品详情优化三板斧-拆分-多级缓存-GC调参
后端·缓存
難釋懷1 天前
Nginx-proxy缓存断点续传缓存 range
运维·nginx·缓存
杨运交1 天前
[053][核心模块]Java枚举缓存与ORM集成实践
java·开发语言·缓存
liulilittle1 天前
LLM推理中的KV缓存与跨请求前缀复用:机制、条件与提示词
缓存·ai·llm
智码看视界1 天前
Day33-数据层 × 中间件AI化篇:Redis缓存经典问题-击穿、穿透、雪崩的终极解决方案
数据库·redis·缓存·中间件·穿透·雪崩·击穿
難釋懷1 天前
Nginx-proxy缓存清理
运维·nginx·缓存