牛客热题:设计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

相关推荐
何以解忧,唯有..11 小时前
深入理解与应对:Redis 缓存雪崩、击穿、穿透三大经典问题
redis·缓存·mybatis
启雀AI15 小时前
培训平台移动端离线学习方案设计与实现:视频缓存、断点续传与进度同步的工程实践
android·学习·缓存·音视频·企业lms
福大大架构师每日一题17 小时前
agno v2.9.0发布:身份感知调度、缓存隔离、安全加固与组件重建全面升级
安全·缓存
何以解忧,唯有..17 小时前
Redis 五种核心数据类型详解与经典使用场景总结
数据库·redis·缓存
零域码客1 天前
Redis 双刃剑:缓存与分布式锁的本质区别
redis·分布式·缓存·并发控制·后端架构
野生技术架构师2 天前
Redis 和 MySQL 如何保证数据一致性?先更新数据库还是先删缓存,延迟双删、MQ、Canal 一次讲透
数据库·redis·缓存
愈努力俞幸运2 天前
token,context window,top_p,temperature,skill,Harness Engineering
数据库·redis·缓存
Patrick在香港2 天前
Claude API 成本直降90%:Prompt Caching 提示词缓存 Python 实战
python·缓存·prompt
NeilYuen3 天前
【vemory】高性能KV存储AOF方案设计
linux·c++·redis·缓存
LuminousCPP3 天前
数据结构基础篇(二):顺序表与链表全方位对比|从内存布局到 CPU 缓存理解底层差异
c语言·数据结构·经验分享·链表·缓存