Leetcode——LRU 缓存机制

Posted Yawn,

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode——LRU 缓存机制相关的知识,希望对你有一定的参考价值。

1. 题目

2. 题解

双链表中实现的方法:

  • 链表初始化
  • 添加元素到双链表尾部(同时意味着该元素最近使用过)
  • 删除某个结点(非头结点)
  • 删除并返回头结点(意味着移除最久未使用过的元素)
  • 返回链表当前长度

LRU 缓存中的方法:

  • 1.初始化,get,put方法
  • 2.设置某元素最近已使用makeRecently(原map中已有该元素)
  • 3.添加最近使用过的元素addRecently(原map中不存在该键值对,新元素)
  • 4.删除某个key对应的元素
  • 5.删除最久未使用过的元素 2.中的方法也可以直接在get和put方法中实现,可以减少部分冗余
class LRUCache {

    class DLinkedNode {
        int key;
        int value;
        DLinkedNode pre;
        DLinkedNode next;
        public DLinkedNode() {};
        public DLinkedNode(int ikey, int ivalue) {
            key = ikey;
            value = ivalue;
        }
    }

    private Map<Integer, DLinkedNode> cache = new HashMap<>();
    private int size;
    private int capacity;
    private DLinkedNode head, tail;

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

        head = new DLinkedNode();
        tail = new DLinkedNode();
        // 使用伪头部和伪尾部节点,减少边界判断
        head.next = tail;
        tail.pre = head;
    }
    
    public int get(int key) {
        DLinkedNode node = cache.get(key);
        if(node == null)
            return -1;
        
        // 如果 key 存在,先通过哈希表定位,再移到头部
        moveToHead(node);
        return node.value;
    }
    
    public void put(int key, int value) {
        DLinkedNode node = cache.get(key);
        if (node == null) {
            // 如果 key 不存在,创建一个新的节点
            DLinkedNode newNode = new DLinkedNode(key, value);
            // 添加进哈希表
            cache.put(key, newNode);
            // 添加至双向链表的头部
            addToHead(newNode);
            size++;
            if (size > capacity) {
                // 如果超出容量,删除双向链表的尾部节点
                DLinkedNode tail = removeTail();
                // 删除哈希表中对应的项
                cache.remove(tail.key);
                size--;
            }
        } else {
            node.value = value;
            moveToHead(node);
        }
    }

    private void addToHead(DLinkedNode node) {  //插入至头结点
        node.pre = head;
        node.next = head.next;
        node.next.pre = node;
        head.next = node;
    }
 
    private void removeNode(DLinkedNode node) { //删该节点结点
        node.pre.next = node.next;
        node.next.pre = node.pre;
    }

    private void moveToHead(DLinkedNode node) {	//移动到头结点:删该节点,插入到头结点
        removeNode(node);
        addToHead(node);
    }

    private DLinkedNode removeTail() {     //移除尾节点
        DLinkedNode res = tail.pre;       //尾节点的前一个就是真正的尾节点
        removeNode(res);
        return res;             //返回尾节点是为了对应删除Map中的节点
    }
}

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

以上是关于Leetcode——LRU 缓存机制的主要内容,如果未能解决你的问题,请参考以下文章

精选力扣500题 第2题 LeetCode 146. LRU 缓存机制 c++详细题解

LeetCode 146. LRU 缓存机制

[Leetcode]146.LRU缓存机制

Leetcode No.146 LRU 缓存机制

LeetCode #146 LRU缓存机制

leetcode 146. LRU缓存机制