2025年- H42-Lc150 --146. LRU缓存(哈希表,双链表)需二刷--Java版

1.题目描述

2.思路

LRU(最近最少使用):如果缓存的容量为2,刚开始的两个元素都入栈。之后该2元素中有其中一个元素(重点元素)被访问。把最近访问过的重点元素保留,另一个边缘元素就得离开缓存了。

下面是leetcode思路:

总结:

(1)创建一个哈希表和双向链表。链表头部是最近刚使用过的元素,尾部是最近不经常使用的元素。

(2)put(),首先如果新加入的元素在哈希表中不存在,则直接创建新节点加入到map中。如果双向链表的节点数超过链表容量,则剔除尾部节点(包括它的值)。如果新加入的元素存在(key存在),我们通过get进行定位,把节点值进行更新,移动到头部(说明是最近刚被访问的)

(3)get(),如果get(key)不存在直接返回-1,如果key存在,说明key节点是最近被使用的节点。通过哈希表定位到双向链表的位置,并将其移动到双向链表的头部,返回该节点的值。

3.代码实现

java 复制代码
class LRUCache {

    class doubleLinkedNode{
        int key;
        int value;
        doubleLinkedNode prev;
        doubleLinkedNode next;

        public doubleLinkedNode() {
        }

        public doubleLinkedNode(int key, int value) {
            this.key = key;
            this.value = value;
        }
    }
    private Map<Integer,doubleLinkedNode> cache=new HashMap<Integer,doubleLinkedNode>();
    private int size;
    private int capacity;
    private doubleLinkedNode head;
    private doubleLinkedNode tail;

    public LRUCache(int capacity) {
        this.size=0;
        this.capacity=capacity;

        //使用伪头部和伪尾部节点
        head=new doubleLinkedNode();
        tail=new doubleLinkedNode();
        head.next=tail;
        tail.prev=head;

    }

    public int get(int key) {
        doubleLinkedNode node=cache.get(key);
        if(node==null)
        {
            return -1;
        }
        //如果key存在,通过哈希表定位,再移动到头部
        moveToHead(node);
        return node.value;

    }

    public void put(int key, int value) {
        doubleLinkedNode node=cache.get(key);
        if(node==null)
        {
            //2.如果key不存在,则创建一个新的节点
            doubleLinkedNode newNode=new doubleLinkedNode(key,value);
            //添加到哈希表
            cache.put(key,newNode);

            //添加到双向链表的头部
            addToHead(newNode);

            size++;
           // 如果添加的数量超出容量
            if(size>capacity)
            {
                //超出容量,说明要删除双向链表的尾部节点
                doubleLinkedNode tail=removeTail();
                //删除哈希表中对应的项,删尾部节点对应的key值
                cache.remove(tail.key);
                size--;
            }
        }
        else{
            //如果key存在,先通过哈希表定位,再修改value,并移动到头部
            node.value=value;
            moveToHead(node);
        }

    }
    private void addToHead(doubleLinkedNode node)
    {
        node.prev=head;
        node.next=head.next;
        head.next.prev=node;
        head.next=node;

    }
    private void removeNode(doubleLinkedNode node)
    {
        node.prev.next=node.next;
        node.next.prev=node.prev;
    }

    private void moveToHead(doubleLinkedNode node)
    {
        removeNode(node);
        addToHead(node);
    }
    private doubleLinkedNode removeTail()
    {
        doubleLinkedNode res=tail.prev;
        removeNode(res);
        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);
 */
相关推荐
hhhjhl9 分钟前
Undici 跨端三方库仓颉适配全流程
java·开发语言·ubuntu
wangchunyu11419 分钟前
JAVA JVM内存结构与运行时数据区
java·开发语言·jvm
光锥智能39 分钟前
海康机器人举行2026移动机器人新品发布会:箱式存拣升级,「明智」系列发布
java·前端·机器人
行思理1 小时前
Nginx 跨站请求(CORS)配置完全指南:从原理到生产实践
java·前端·nginx
小溪学编程1 小时前
Spring @Bean 与 @Component 注解的区别详解
java·后端·spring
Wang's Blog1 小时前
Java 项目实战: 交友项目 - 圈子互动章总结与自检清单
java·bootstrap·交友
xyouyuweizhu2 小时前
字节流与字符流:Java IO 的两条主线该怎么选
java·开发语言·python
代码方舟2 小时前
零信任架构实战:基于天远人企关联构建自动化供应链核心企业关联穿透与利益冲突审查网关
java·人工智能·架构·自动化
liyi_hz20083 小时前
O2OA(翱途) V10.1 即将发布|功能再升级,安全再加固,协同更高效!
java·javascript·windows·开源软件
骑着蜗牛撵大象3273 小时前
AI Agent 工程化开发实战(三):用 StateGraph 给智能体搭一条可回放的状态流水线
java·开发语言·jvm·ai·状态管理·langgraph·stategraph