力扣HOT100 Q146LRU缓存

需要创建一个map和一个双向链表

map中key为输入的key,value为一个Node结点

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

class LRUCache {

    /**
     * 双向链表节点
     */
    class Node {
        int key, value;
        // 前驱和后继
        Node prev, next;

        /**
         * 全参构造
         * @param k
         * @param v
         */
        public Node(int k, int v) {
            key = k;
            value = v;
        }

        /**
         * 空参构造
         */
        public Node() {

        }
    }

    // 缓存
    private Map<Integer, Node> cache = new HashMap<>();

    // 当前缓存大小
    private int size;

    // 总缓存大小
    private int capacity;

    // 双向链表的头尾哨兵节点,不存储数据
    private Node head, tail;

    /**
     * 初始化双向链表
     * @param capacity
     */
    public LRUCache(int capacity) {
        this.capacity = capacity;
        head = new Node();
        tail = new Node();
        head.next = tail;
        tail.prev = head;
    }

    /**
     * 获得key
     * @param key
     * @return
     */
    public int get(int key) {
        Node node = cache.get(key);
        if (node == null) {
            return -1;
        }
        // 如果key存在,需要移动双向链表
        moveToHead(node);
        return node.value;
    }

    /**
     * 添加结点
     * @param key
     * @param value
     */
    public void put(int key, int value) {
        // 先判断是否存在结点
        Node node = cache.get(key);
        // 如果不存在,需要创建节点
        if (node == null) {
            // 创建结点
            Node newNode = new Node(key, value);
            // 加入哈希表
            cache.put(key, newNode);
            // 加入双向链表
            addToHead(newNode);
            // 当前容量 +1
            size++;
            // 判断是否超出容量
            if (size > capacity) {
                // 删除双向链表的尾节点
                Node lastNode = removeTail();
                // 删除哈希表中的key-value
                cache.remove(lastNode.key);
                size--;
            }
        } else {
            // 没有超出容量
            // 修改value
            node.value = value;
            // 移动到头结点
            moveToHead(node);
        }
    }

    /**
     * 移除尾节点
     * @return 删除的节点
     */
    private Node removeTail() {
        Node prev = tail.prev;
        moveToList(prev);
        return prev;
    }

    /**
     * 移除结点并且添加到头结点
     * @param node
     */
    private void moveToHead(Node node) {
        moveToList(node);
        addToHead(node);
    }


    /**
     * 添加到链表头部
     * @param node
     */
    private void addToHead(Node node) {
        node.next = head.next;
        node.prev = head;
        head.next.prev = node;
        head.next = node;
    }

    /**
     * 把当前结点移除链表
     * @param node
     */
    private void moveToList(Node node) {
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }


}
相关推荐
梦梦代码精16 小时前
BuildingAI 上部署自定义工作流智能体:5 个实用技巧
大数据·人工智能·算法·开源软件
Zephyr_017 小时前
Leedcode算法题
java·算法
流年如夢17 小时前
栈和列队(LeetCode)
数据结构·算法·leetcode·链表·职场和发展
Hello.Reader18 小时前
算法基础(十)——分治思想把大问题拆成小问题
java·开发语言·算法
绛橘色的日落(。・∀・)ノ19 小时前
机器学习之评估与偏差方差分析
算法
消失的旧时光-194319 小时前
C语言对象模型系列(四)《Linux 内核里的 container_of 到底是什么黑魔法?》—— 一篇讲透 Linux 内核的“对象模型”核心技巧
linux·c语言·算法
.柒宇.20 小时前
Redis主从复制集群搭建详解
数据库·redis·缓存·主从复制
AI_Ming20 小时前
从0开始学AI:层归一化,原来是这回事!
算法·ai编程
WL_Aurora20 小时前
备战蓝桥杯国赛【Day 8】
算法·蓝桥杯