【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,以此为准来一移除
相关推荐
南境十里·墨染春水2 小时前
C++传记(面向对象)虚析构函数 纯虚函数 抽象类 final、override关键字
开发语言·c++·笔记·算法
2301_797172753 小时前
基于C++的游戏引擎开发
开发语言·c++·算法
有为少年4 小时前
告别“唯语料论”:用合成抽象数据为大模型开智
人工智能·深度学习·神经网络·算法·机器学习·大模型·预训练
比昨天多敲两行4 小时前
C++ 二叉搜索树
开发语言·c++·算法
Season4504 小时前
C++11之正则表达式使用指南--[正则表达式介绍]|[regex的常用函数等介绍]
c++·算法·正则表达式
Tisfy4 小时前
LeetCode 2839.判断通过操作能否让字符串相等 I:if-else(两两判断)
算法·leetcode·字符串·题解
问好眼4 小时前
《算法竞赛进阶指南》0x04 二分-1.最佳牛围栏
数据结构·c++·算法·二分·信息学奥赛
会编程的土豆4 小时前
【数据结构与算法】优先队列
数据结构·算法
minji...6 小时前
Linux 进程信号(二)信号的保存,sigset_t,sigprocmask,sigpending
linux·运维·服务器·网络·数据结构·c++·算法
罗湖老棍子6 小时前
最大数(信息学奥赛一本通- P1549)(洛谷-P1198)
数据结构·算法·线段树·单点修改 区间求最大值