【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,以此为准来一移除
相关推荐
AI软著研究员40 分钟前
程序员必看:软著不是“面子工程”,是代码的“法律保险”
算法
FunnySaltyFish1 小时前
什么?Compose 把 GapBuffer 换成了 LinkBuffer?
算法·kotlin·android jetpack
颜酱2 小时前
理解二叉树最近公共祖先(LCA):从基础到变种解析
javascript·后端·算法
地平线开发者18 小时前
SparseDrive 模型导出与性能优化实战
算法·自动驾驶
董董灿是个攻城狮18 小时前
大模型连载2:初步认识 tokenizer 的过程
算法
地平线开发者19 小时前
地平线 VP 接口工程实践(一):hbVPRoiResize 接口功能、使用约束与典型问题总结
算法·自动驾驶
罗西的思考19 小时前
AI Agent框架探秘:拆解 OpenHands(10)--- Runtime
人工智能·算法·机器学习
HXhlx1 天前
CART决策树基本原理
算法·机器学习
Wect1 天前
LeetCode 210. 课程表 II 题解:Kahn算法+DFS 双解法精讲
前端·算法·typescript
颜酱1 天前
单调队列:滑动窗口极值问题的最优解(通用模板版)
javascript·后端·算法