【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,以此为准来一移除
相关推荐
mit6.8247 分钟前
dijk|tire+floyd+dp %
算法
独自破碎E22 分钟前
【总和拆分 + 双变量遍历】LCR_012_寻找数组的中心下标
数据结构·算法
WBluuue22 分钟前
Codeforces 1076 Div3(ABCDEFG)
c++·算法
u01092727134 分钟前
模板编译期排序算法
开发语言·c++·算法
GIS瞧葩菜42 分钟前
Cesium 轴拖拽 + 旋转圈拖拽 核心数学知识
人工智能·算法·机器学习
m0_686041611 小时前
C++中的适配器模式变体
开发语言·c++·算法
txzrxz1 小时前
结构体排序,双指针,单调栈
数据结构·算法·双指针算法·单调栈·结构体排序
AndrewHZ1 小时前
【AI黑话日日新】什么是AI智能体?
人工智能·算法·语言模型·大模型·llm·ai智能体
wWYy.1 小时前
算法:二叉树最大路径和
数据结构·算法
葱明撅腚1 小时前
利用Python挖掘城市数据
python·算法·gis·聚类