HashMap+双向链表实现LRU算法

请你设计并实现一个满足  LRU (最近最少使用) 缓存 约束的数据结构。

实现 LRUCache 类:

  • LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
  • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。

class LRUCache {
    // LRU缓存 最近最少使用---思路:用双链表来模拟,HashMap来
    int capacity;   //容量
    DoubleList cache;
    HashMap<Integer,Node> map;

    //初始化
    public LRUCache(int capacity) {
        this.capacity = capacity;
        cache = new DoubleList();
        map = new HashMap<>();
    }
    
    //如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1
    public int get(int key) {
        if(map.containsKey(key)){
            //如果存在,调整顺序
            Node tempNode =  map.get(key);
            cache.remove(tempNode);
            cache.addLast(tempNode);
            return tempNode.val;
        }else{
            return -1;
        }
    }
    //如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value
    public void put(int key, int value) {
        if(map.containsKey(key)){
            //如果存在
            Node tempNode = map.get(key);
            cache.remove(tempNode);
            Node newNode = new Node(key,value);
            map.put(key,newNode);
            cache.addLast(newNode);
        }else{
            //如果不存在
            //判断满了没有
            if(map.size()==capacity){
                //满了--删除最久没访问的
                Node first = cache.removeFirst();
                map.remove(first.key);
                //再新添加
            }
            //如果没满
            Node node = new Node(key,value);
            map.put(key,node);
            cache.addLast(node);

            }  
    }
    //定义双向链表的节点
    class Node{
        int key;
        int val;
        Node pre;
        Node next;
        //构造
        public Node(int key,int val){
            this.key = key;
            this.val = val;
        }
    }
    //定义双向链表
    class DoubleList{
        int size;
        Node head,tail;

        public DoubleList(){
            //初始化链表
            head = new Node(0,0);
            tail = new Node(0,0);
            head.next = tail;
            tail.pre = head;
            size = 0;
        }

        //末尾添加节点
        public void addLast(Node x){
            tail.pre.next = x;
            x.pre=tail.pre;
            x.next = tail;
            tail.pre = x;
            size++;
        }
        //删除最近没访问的节点并且返回这个节点--head是虚拟头节点
        public Node removeFirst(){
            Node first = head.next;
            head.next = head.next.next;
            head.next.pre=head;
            size--;
            return first;
        }

        //删除指定节点
        public void remove(Node node){
            node.pre.next=node.next;
            node.next.pre=node.pre;
            size--;

        }
    }
}

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

全部评论
mark一下大佬
点赞 回复 分享
发布于 昨天 23:21 河南

相关推荐

01-27 23:08
门头沟学院 Java
过年了,不要再讨论什么SpringBoot、微服务、高并发了。你背着贴满JetBrains贴纸的MacBookPro回到家,发现写了半年的DDD架构在七大姑八大姨眼里还不如村口王二狗开的淘宝店。发小们晒着字节跳动36薪的年终奖,你躲在卫生间用IntelliJ远程连接公司那台8G内存的测试服务器改OOM问题。舅舅举着茅台问你在北京做什么工作,你掏出手机展示Github上fork了2.3k星的xxl-job魔改版,说用责任链模式重构了工作流引擎,饭桌上突然安静得能听见GC日志在滚动。你暗笑他们不懂JVM调优的浪漫,不明白你通宵画架构图的仪式感,更看不懂你博客园里那篇《从零实现分布式事务中间件》的技术干货。当大姨炫耀女婿在蚂蚁金服拿了P7,二舅吹嘘侄子在鹅厂做游戏年终奖百万时,你爸默默给你夹了个鸡腿:&amp;quot;我儿电脑上那个彩虹圆圈转得越久,工资就越稳当对吧?&amp;quot;你半夜两点蹲在院子4G信号最好的角落抢修生产事故,发现阿里云SLB的流量费比老家杀猪菜还贵。家族群疯狂转发拼多多砍价链接,你反手甩出刚通过的Apache&nbsp;Committer认证,配文&amp;quot;成为RocketMQ社区贡献者&amp;quot;。表弟表妹们晒着环球影城VIP导览,你在朋友圈用PlantUML图解过山车排队算法与Disruptor队列的异同,最后补了句&amp;quot;求大厂内推可过字节八股文&amp;quot;。零点钟声响起时,你布满老茧的手指还在Command键上疯狂抽搐,远处烟花在IDE的暗黑主题背景上炸出彩虹括号。凌晨改完第N版秒杀系统方案,你摸着发烫的M1芯片,屏幕上飘着的NullPointerException堆栈在视网膜里叠成三室一厅的轮廓。隔壁屋传来父母的梦话:&amp;quot;这孩子天天说什么要当Java架构师,可连对象都new不出来一个...&amp;quot;,尾音混着WindowsUpdate的关机提示音,在FullGC的STW中碎成永久代的记忆。#实习# #java# #没有实习经历,还有机会进大厂吗# #过年期间可能会经历的尴尬瞬间#
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务