[LeetCode146. LRU 缓存机制] | 刷题打卡

106 阅读2分钟

题目描述

运用你所掌握的数据结构,设计和实现一个  LRU (最近最少使用) 缓存机制 。 实现 LRUCache 类:

  • LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
  • void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。

解题思路

今天就来手撕这道经典的LRU算法,题目的要求是要保证get和put方法在O(1)的时间复杂度,自然想到用hashmap来保存数组,还需要定义一个双向链表,需要一个计算器来计算map中保存了多少个数,如果超过容量,就需要删除头节点。

AC 代码

class LRUCache {
    //定义一个双向链表
    public class Node{
        private Node pre;
        private Node next;
        private int val;
        private int key;
        public Node(int key,int val){
            this.key=key;
            this.val=val;
        }
    }
    private  Node head,tail;
    private  int size;
    private HashMap<Integer,Node> map;
    private int count;
    public LRUCache(int capacity) {
        this.size=capacity;
        this.map=new HashMap<>();
        this.head=new Node(0,0);
        this.tail=head;
        this.count=0;
    }
    private void removeHead(){
        map.remove(head.next.key);
        head.next=head.next.next;
        if(head.next!=null){
            head.next.pre=head;
        }
    }
    private void appendTotail(Node node){
        tail.next=node;
        node.pre=tail;
        tail=node;
    }
    public int get(int key) {
        if(!map.containsKey(key)){
            return -1;
        }
        Node node=map.get(key);
        if(node!=tail){
            //删除该节点
            Node pre=node.pre;
            pre.next=node.next;
            pre.next.pre=pre;
            appendTotail(node);
        }
        return node.val;
    }
    
    public void put(int key, int value) {
        Node cur=new Node(key,value);
        //如果包含就不需要考虑了容量的大小
        if(map.containsKey(key)){
            Node node=map.get(key);
            if(node!=tail){
                //删除该节点
                Node pre=node.pre;
                pre.next=node.next;
                pre.next.pre=pre;
            }else{
                tail=tail.pre;
            }
        }else{
            if(count<size){
                count++;
            }else{
                removeHead();
            }
        }
        appendTotail(cur);
        map.put(key,cur);
    }
}

总结

首先定义双向链表要加上key值,这样删除头节点的时候,就可以直接删除map中的值,然后需要加强的是put方法