leetcode做题笔记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 ,则应该 逐出 最久未使用的关键字。

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

思路一:双向链表

c语言解法

cpp 复制代码
struct LRUInfo{
    int val;
    int value;
    struct LRUInfo* pre;
    struct LRUInfo* next;
};

typedef struct {
    int top;
    int total;
    struct LRUInfo * head;
    struct LRUInfo * rear;
    struct LRUInfo lruinfo[10001];
} LRUCache;

LRUCache* lRUCacheCreate(int capacity) {
    LRUCache* obj = calloc(1, sizeof(LRUCache));
    obj->total = capacity;
    obj->head = calloc(1, sizeof(struct LRUInfo));
    obj->rear = calloc(1, sizeof(struct LRUInfo));
    obj->head->next = obj->rear;
    obj->rear->pre = obj->head;
    return obj;
}

int lRUCacheGet(LRUCache* obj, int key) {
    if (obj->lruinfo[key].val == 1) {
        obj->lruinfo[key].pre->next = obj->lruinfo[key].next;
        obj->lruinfo[key].next->pre = obj->lruinfo[key].pre;
        obj->rear->pre->next = obj->lruinfo + key;
        obj->lruinfo[key].pre = obj->rear->pre;
        obj->lruinfo[key].next = obj->rear;
        obj->rear->pre = obj->lruinfo + key;
        return obj->lruinfo[key].value;
    }
    return -1;
}

void lRUCachePut(LRUCache* obj, int key, int value) {
    if (obj->lruinfo[key].val == 0 && obj->top < obj->total) {
        (obj->top)++;
        obj->rear->pre->next = obj->lruinfo + key;
        obj->lruinfo[key].pre = obj->rear->pre;
        obj->lruinfo[key].next = obj->rear;
        obj->lruinfo[key].val = 1;
        obj->lruinfo[key].value = value;
        obj->rear->pre = obj->lruinfo + key;
    } else if (obj->lruinfo[key].val == 1){
        obj->lruinfo[key].pre->next = obj->lruinfo[key].next;
        obj->lruinfo[key].next->pre = obj->lruinfo[key].pre;
        obj->rear->pre->next = obj->lruinfo + key;
        obj->lruinfo[key].pre = obj->rear->pre;
        obj->lruinfo[key].next = obj->rear;
        obj->lruinfo[key].value = value;
        obj->rear->pre = obj->lruinfo + key;
    } else if (obj->lruinfo[key].val == 0 && obj->top >= obj->total && obj->head->next != NULL) {
        obj->lruinfo[key].val = 1;
        obj->lruinfo[key].value = value;
        obj->rear->pre->next = obj->lruinfo + key;
        obj->lruinfo[key].pre = obj->rear->pre;
        obj->lruinfo[key].next = obj->rear;
        obj->rear->pre = obj->lruinfo + key;
        obj->head->next->val = 0;
        obj->head->next = obj->head->next->next;
        obj->head->next->pre = obj->head;       
    }
    return;
}

void lRUCacheFree(LRUCache* obj) {
    free(obj);
}

/**
 * Your LRUCache struct will be instantiated and called as such:
 * LRUCache* obj = lRUCacheCreate(capacity);
 * int param_1 = lRUCacheGet(obj, key);
 
 * lRUCachePut(obj, key, value);
 
 * lRUCacheFree(obj);
*/

分析:

本题要实现LRU缓存实现双向链表的各个操作后即可解决,删除方法利用前驱节点的指针才能满足O(1)的时间复杂度,get方法利用前驱节点达到O(1)的时间复杂度

总结:

本题考察对LRU缓存的实现,考虑到各个方法的实现的时间复杂度要求在O(1),所以采用双向链表保证时间复杂度,最后实现各个方法即可解决

相关推荐
蒸蒸yyyyzwd13 小时前
关于 AI 开发相关的一些面经。
笔记·学习
2603_9696948514 小时前
JDBC 基础学习笔记:API 核心原理解析与 CRUD 代码实操
数据库·笔记·mysql·学习方法·database·sql注入
迪康coolmu14 小时前
出差终端数据安全落地实战:基于迪康端点安全一体化管理系统的四道防线实践
运维·服务器·经验分享·笔记·其他·安全·php
code2cat17 小时前
【随笔】推理准入控制:请求进来之前,先给KV缓存留出位置
缓存·大语言模型·vllm
文丑颜不良啊17 小时前
LeetCode2261~2280题目解析
java·leetcode
无咎.lsy18 小时前
《机器学习》笔记
笔记·机器学习
坤坤子吖19 小时前
Linux网络编程:TCP服务器的多进程与多线程实现
linux·服务器·开发语言·网络·c++·笔记·学习
徐小黑ACG19 小时前
Redis-基础
数据库·redis·缓存
蒸蒸yyyyzwd20 小时前
后端相关学习笔记。
笔记·学习
旖旎夜光21 小时前
【C++ 基础入门】C++ 多态(上):虚函数、重写、override/final 与抽象类
开发语言·c++·笔记·学习