【LeetCode】Day10-LRU缓存

阅读 14

2022-03-13

题目

146. LRU 缓存【中等】

题解

关键问题是如何查找最久未使用的关键字,想过构建新的类(key,value,time),用优先队列存,但是需要排序,时间复杂度大于O(1),其余方法似乎都需要排序,不可能用O(1)的时间复杂度完成

官方给出的解法是用哈希表+双向链表,原因如下:

因此采用双向链表的思路是:

  1. 最近访问的结点放第一个【头插】
  2. 最久未使用的结点放末尾,capacity不够,则删除最后一个结点【尾删】
  3. 访问已有结点,则将它挪到第一个位置【删除+头插】
//结点
class Node{
    public int key;
    public int value;
    public Node prev,next;
    public Node(){
        prev=null;
        next=null;
    }
    public Node(int k,int v){
        key=k;
        value=v;
        prev=null;
        next=null;
    }
}
//双向链表
class DoubleList{
    private Node head;//虚拟头结点
    private Node tail;//虚拟尾结点

    //构造方法
    public DoubleList(){
        head=new Node();
        tail=new Node();
        head.next=tail;
        tail.prev=head;
    }
    //头插
    public void insert(Node p){
        p.next=head.next;
        p.prev=head;
        head.next=p;
        p.next.prev=p;
    }
    //尾删
    public Node remove(){
        Node p=tail.prev;
        p.prev.next=tail;
        tail.prev=p.prev;
        return p;
    }
    //删除任意结点p
    public void remove(Node p){
        p.prev.next=p.next;
        p.next.prev=p.prev;
    }
}
class LRUCache {
    private int capacity;
    private Map<Integer,Node>hashMap;//哈希表
    private DoubleList doubleList;//双向链表
    public LRUCache(int capacity) {
        this.capacity=capacity;
        hashMap=new HashMap<Integer,Node>();
        doubleList=new DoubleList();
    }
    
    public int get(int key) {
        if(hashMap.containsKey(key)){
            Node p=hashMap.get(key);
            doubleList.remove(p);//删除原位置
            doubleList.insert(p);//头插
            return p.value;
        }
        return -1;
    }
    
    public void put(int key, int value) {
        //key已经存在
        if(get(key)!=-1){//get(key)中已经包含了把key结点挪到第一个的操作
            hashMap.get(key).value=value;
        }
        //key不存在
        else{
            Node p=new Node(key,value);
            //超过capacity
            if(hashMap.size()>=capacity){
                Node tmp=doubleList.remove();//尾删
                hashMap.remove(tmp.key);//哈希表中删除
            }    
            doubleList.insert(p);//头插
            hashMap.put(key,p);
        }
    }
}

主要考察双向链表的应用和实现,需要熟记

精彩评论(0)

0 0 举报