【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,以此为准来一移除
相关推荐
双叶8362 小时前
(C语言)写一个递归函数DigitSum(n),输入一个非负整数,返回组成它的数字之和(递归函数)
c语言·开发语言·数据结构·算法·游戏
BineHello2 小时前
强化学习 - PPO控制无人机
人工智能·算法·自动驾驶·动态规划·无人机·强化学习
阿饼2402 小时前
算法——层序遍历和中序遍历构造二叉树
数据结构·算法
yqcoder3 小时前
Redis 的应用场景
数据库·redis·缓存
申未曲3 小时前
如何解决Redis的缓存雪崩、缓存击穿、缓存穿透?
redis·缓存·mybatis
贫道绝缘子3 小时前
Leetcode-132.Palindrome Partitioning II [C++][Java]
java·c++·算法·leetcode
spatial_coder4 小时前
deepseek GRPO算法保姆级讲解(数学原理+源码解析+案例实战)
人工智能·算法
earthzhang20214 小时前
《Python深度学习》第四讲:计算机视觉中的深度学习
人工智能·python·深度学习·算法·计算机视觉·numpy·1024程序员节
小咖拉眯5 小时前
蓝桥杯进制问题秒破解法|冲击省一题单(二)
java·数据结构·算法·蓝桥杯