Java算法_ LRU 缓存(LeetCode_Hot100)

题目描述:请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
获得更多?算法思路:代码文档,算法解析的私得。
运行效果

完整代码

bash 复制代码
import java.util.HashMap;
import java.util.Map;

/**
 * 2 * @Author: LJJ
 * 3 * @Date: 2023/8/7 13:14
 * 4
 */
public class LRUCache {
    class Node{
        int key;
        String value;
        Node prev;
        Node next;

        public Node(int key , String value){
            this.key = key;
            this.value = value;
        }
    }

    private int capacity;
    private Map<Integer,Node> cache;
    private Node head;
    private Node tail;

    // 初始化LRUCache类的构造函数,
    // 使用了一个哨兵节点的技巧,将head和tail初始化为哨兵节点,并不存储具体的键值对。
    // 哨兵节点可以简化链表的操作,避免处理头部和尾部节点时需要特殊处理的情况。
    public LRUCache(int capacity){
        this.capacity = capacity;
        cache = new HashMap<>();
        //初始化头尾节点;
        head = new Node(-1, "-1");
        tail = new Node(-1, "-1");
        head.next = tail;
        tail.prev = head;
    }

    public String get(int key){
       if (cache.containsKey(key)){
            Node node = cache.get(key);
            //将查到的节点移动到链表头部
            removeNode(node);
            addToHead(node);
            return node.value;
        }
        return "-1";
    }

    public void put(int key, String value){
        if (cache.containsKey(key)){
            Node node = cache.get(key);
            node.value = value;
            //将更新后的节点移动到链表头部
            removeNode(node);
            addToHead(node);
        }else {
            if (cache.size() >= capacity){

                //如果缓存已满,需要移除最久未使用的节点(即链表尾部节点)
                cache.remove(tail.prev.key);
                removeNode(tail.prev);
            }
            Node newNode = new Node(key,value);
            cache.put(key,newNode);
            //将新的节点插入链表头部
            addToHead(newNode);
        }
    }

    // 将节点插入链表头部
    private void addToHead(Node node){
        node.next = head.next;
        head.next.prev = node;
        head.next = node;
        node.prev = head;
    }

    //移除节点
    private void removeNode(Node node){
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }

    private static void printCache(Node head){
        Node current = head;
        while (current != null){
            System.out.print("(" + current.key + ", " + current.value + ") -> ");
            current = current.next;
        }
        System.out.println("null");
    }
    public static void main(String[] args) {
        LRUCache lruCache = new LRUCache(3);

        // 插入键值对 (1, "A")
        lruCache.put(1, "A");
        // 插入键值对 (2, "B")
        lruCache.put(2, "B");
        // 插入键值对 (3, "C")
        lruCache.put(3, "C");

        // 此时缓存状态为:3 -> 2 -> 1,其中1是最近访问的,3是最久未使用的
        System.out.println("初始缓存状态为:");
        printCache(lruCache.head);
        // 获取键1对应的值,输出"A"
        System.out.println(" // 获取键1对应的值:"+lruCache.get(1));

        // 此时缓存状态不变:1 -> 3 -> 2
        System.out.println("获取键1对应的值,输出\"A\"后的缓存状态为:");
        printCache(lruCache.head);
        // 插入键值对 (4, "D"),此时缓存已满,需要逐出最久未使用的键值对,即键2 -> 值B被逐出
        lruCache.put(4, "D");

        // 此时缓存状态为:4 -> 1 -> 3,其中3是最久未使用的,4是最近访问的
        System.out.println("插入键值对 (4, \"D\"),此时缓存已满,需要逐出最久未使用的键值对,即键2 -> 值B被逐出的缓存状态为:");
        printCache(lruCache.head);
        // 获取键2对应的值,由于键2已经被逐出,输出-1
        System.out.println("获取键2对应的值:"+lruCache.get(2));

        // 此时缓存状态不变:4 -> 1 -> 3
        System.out.println("获取键2对应的值,由于键2已经被逐出,输出-1的缓存状态为:");
        printCache(lruCache.head);
        // 插入键值对 (5, "E"),此时缓存已满,需要逐出最久未使用的键值对,即键3 -> 值C被逐出
        lruCache.put(5, "E");

        // 此时缓存状态为:5 -> 4 -> 1,其中1是最久未使用的,5是最近访问的
        System.out.println("插入键值对 (5, \"E\"),此时缓存已满,需要逐出最久未使用的键值对,即键3 -> 值C被逐出的缓存状态为:");
        printCache(lruCache.head);
        // 获取键3对应的值,由于键3已经被逐出,输出-1
        System.out.println("获取键3对应的值:"+lruCache.get(3));

        // 此时缓存状态不变:5 -> 4 -> 1
        System.out.println(" // 获取键3对应的值,由于键3已经被逐出,输出-1的缓存状态为:");
        printCache(lruCache.head);
    }
}
相关推荐
毕业设计制作和分享35 分钟前
springboot150基于springboot的贸易行业crm系统
java·vue.js·spring boot·后端·毕业设计·mybatis
电子_咸鱼3 小时前
LeetCode——Hot 100【电话号码的字母组合】
数据结构·算法·leetcode·链表·职场和发展·贪心算法·深度优先
仰泳的熊猫3 小时前
LeetCode:785. 判断二分图
数据结构·c++·算法·leetcode
rit84324994 小时前
基于MATLAB实现基于距离的离群点检测算法
人工智能·算法·matlab
my rainy days6 小时前
C++:友元
开发语言·c++·算法
haoly19896 小时前
数据结构和算法篇-归并排序的两个视角-迭代和递归
数据结构·算法·归并排序
微笑尅乐6 小时前
中点为根——力扣108.讲有序数组转换为二叉搜索树
算法·leetcode·职场和发展
小梁努力敲代码6 小时前
java数据结构--List的介绍
java·开发语言·数据结构
摸鱼的老谭6 小时前
构建Agent该选Python还是Java ?
java·python·agent
lang201509286 小时前
Spring Boot 官方文档精解:构建与依赖管理
java·spring boot·后端