【leetcode hot 100 146】LRU缓存

解法一:(哈希表 + 双向链表)LRU 缓存机制可以通过哈希表辅以双向链表实现,我们用一个哈希表和一个双向链表维护所有在缓存中的键值对。

  • 双向链表按照被使用的顺序存储了这些键值对,靠近头部的键值对是最近使用的,而靠近尾部的键值对是最久未使用的。
  • 哈希表即为普通的哈希映射(HashMap),通过缓存数据的键映射到其在双向链表中的位置。
java 复制代码
class LRUCache {
    class DLinkNode{
        int key;
        int value;
        DLinkNode prev;
        DLinkNode next;
        // 记得写构造函数
        public DLinkNode(){}
        public DLinkNode(int key, int value){this.key=key; this.value=value;}
    }

    private Map<Integer,DLinkNode> mapID = new HashMap<>();
    private int capacity;
    private int size;
    private DLinkNode head,tail;  // 全部放到构造函数去初始化

    public LRUCache(int capacity) {
        this.capacity = capacity;
        this.size = 0;
        head = new DLinkNode();
        tail = new DLinkNode();
        head.next = tail;
        tail.prev = head;
    }
    
    public int get(int key) {
        DLinkNode node = mapID.get(key);
        if(node==null){
            return -1;
        }
        // 将node放到双链表头部,表示刚刚访问过
        moveToHead(node);
        return node.value;
    }
    
    public void put(int key, int value) {
        DLinkNode node = mapID.get(key);
        if(node==null){
            // 不存在:申请node,放在头部,超过数量就删除尾部
            DLinkNode newNode = new DLinkNode(key, value);
            addNode(newNode);
            mapID.put(key,newNode); // mapID也要做相应的put和remove
            size++;
            if(size>capacity){
                DLinkNode tail = deleteTail();
                // mapID.remove(key)不可,要返回删除的key,以此为准来一移除
                mapID.remove(tail.key);
                size--;
            }
        }
        else{
            // 已经存在:修改v值,移到最前面
            node.value = value;
            moveToHead(node);
        }
    }

    private void moveToHead(DLinkNode node){
        removeNode(node);
        addNode(node);
    }

    private DLinkNode removeNode(DLinkNode node){
        node.prev.next = node.next;
        node.next.prev = node.prev;
        return node;
    }

    private void addNode(DLinkNode node){
        node.next = head.next;
        head.next = node;
        node.prev = head;
        node.next.prev = node;
    }

    private DLinkNode deleteTail(){
        DLinkNode res = removeNode(tail.prev);
        return res;
    }
}

/**
 * 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);
 */

注意:

  • 参数的初始化全部放到构造函数去初始化
  • 双链表进行添加和移除时候,mapID也要做相应的putremove
  • mapID进行移除时,mapID.remove(key)不可,要返回删除的key,以此为准来一移除
相关推荐
平行侠5 分钟前
A15 工业路由器IP前缀高速检索与内存压缩系统
网络·tcp/ip·算法
阿旭超级学得完1 小时前
C++11包装器(function和bind)
java·开发语言·c++·算法·哈希算法·散列表
li星野1 小时前
位运算 & 数学 & 高频进阶九题通关(Python + C++)
c++·python·学习·算法
jerryinwuhan1 小时前
hello算法,简单讲(1)
算法·排序算法
y = xⁿ1 小时前
20天速通LeetCodeday15:BFS广度优先搜索
算法·宽度优先
400分2 小时前
吃透RAG核心-----语义检索与关键字检索底层原理
算法·架构
目黑live +wacyltd2 小时前
算法备案:常见驳回原因与应对策略
人工智能·算法
磊 子2 小时前
多态类原理+四种类型转换+异常处理
开发语言·c++·算法
染指11103 小时前
3.AI大模型-token是什么-大模型底层运行机制
人工智能·算法·机器学习
谙弆悕博士4 小时前
快速学C语言——第19章:C语言常用开发库
c语言·开发语言·算法·业界资讯·常用函数