栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

leetcode-146:LRU缓存

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

leetcode-146:LRU缓存

leetcode-146:LRU缓存 链接 LRU 缓存

分析

实现一个最近最少使用的数据结构.同时要求get和put都是常数复杂程度.首先我们先来考虑如何在O(1)时间内获取.显而易见,要想在O(1)时间内获取对应的数据,我们需要用的哈希表,哈希表可以O(1)时间内获取对应key值的val.再然后就是考虑如何判断出最近最少.这个我们使用双链表来维护.每当我们对一个数进行操作之后,就将它添加到链表的头部,这样链表的尾部就是最近最少使用的节点.



code & 注释
class LRUCache {
public:

    // 创建双链表节点
    struct Node{
        // k-v键值对
        int key, val;
        // 左右指针
        Node *left, *right;
        // 初始化方法
        Node(int _key, int _val) : key(_key), val(_val), left(NULL), right(NULL){}
    }*L, *R; // 头尾节点

    // 容量
    int n;
    // 哈希表
    unordered_map hash;

    // 删除一个节点
    void remove(Node* p) {
        // 让当先节点的前一个节点指向当前节点的下一个节点
        p->left->right = p->right;
        // 让当前节点的后一个节点只想当前节点的前一个节点
        p->right->left = p->left;
    }

    // 在头部添加一个节点
    void insert(Node* p) {
        // 当前节点分别指向虚拟头和第一个节点
        p->left = L;
        p->right = L->right;
        // 下两句顺序不能变,如果变化,就无法访问到原来的第一个节点
        // 让与原来的第一个节点指向当前节点
        L->right->left = p;
        // 让虚拟头指向当前节点
        L->right = p;
    }

    LRUCache(int capacity) {
        // 初始化容量
        n = capacity;
        // 创建虚拟头尾节点
        L = new Node(1, 1), R = new Node(1, 1);
        // 初始化双链表
        L->right = R;
        R->left = L;
    }
    
    int get(int key) {
        // 如果当前key不存在直接返回即可
        if (hash.count(key) == 0) return -1;
        // 存在的话,直接获取
        auto p = hash[key];
       	// 从链表中原来的位置删除,添加到虚拟头节点后面
        remove(p);
        insert(p);
        // 返回值
        return p->val;
    }
    
    void put(int key, int value) {
        // 如果当前key不存在,需要新建
        if (hash.count(key) == 0) {
            // 如果已经达到了容量
            if (hash.size() == n) {
                // 删除虚拟尾节点的前一个节点
                auto p = R->left;
                remove(p);
                // 同时在哈希表中删除
                hash.erase(p->key);
                delete p;
            }
            // 创建新节点
            auto p = new Node(key, value);
            // 更新哈希表
            hash[key] = p;
            // 插入双链表头部
            insert(p);
        } else {
            // 如果当前key存在,只用更新value即可
            auto p = hash[key];
            // 更新节点的值
            p->val = value;
            // 从原来的位置删除,添加到双链表头部
            remove(p);
            insert(p);
        }
    }
};


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/697491.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号