LRU

LRU
https://leetcode.cn/problems/lru-cache/description/?envType=study-plan-v2&envId=top-100-liked

class LRUCache {

    HashMap<Integer,DLinkedNode> map;
    int dLinkSize;
    int capacity;
    DLinkedNode head;
    DLinkedNode tail;
    class DLinkedNode{
        int key;
        int value;
        DLinkedNode prior;
        DLinkedNode next;
        public DLinkedNode(){ }
        public DLinkedNode(int key,int value){
             this.key = key;
             this.value = value;
        }
    }

    public LRUCache(int capacity) {
        this.map = new HashMap<>();
        this.dLinkSize = 0;
        this.capacity = capacity;
        this.head = new DLinkedNode();
        this.tail = new DLinkedNode();
        head.next = tail;
        tail.prior = head;
    }

    public int get(int key) {
        if (map.containsKey(key)){
            DLinkedNode node = map.get(key);
            moveNodeToHead(node);
            return node.value;
        }else {
            return -1;
        }
    }

    public void put(int key, int value) {
        if (map.containsKey(key)){
            DLinkedNode node = map.get(key);
            node.value = value;
            moveNodeToHead(node);
        }else if (dLinkSize < capacity){
            DLinkedNode newNode = addNodeHead(key,value);
            map.put(key,newNode);
        }else {
            int curKey = deleteTailNode();
            map.remove(curKey);
            DLinkedNode newNode = addNodeHead(key,value);
            map.put(key,newNode);
        }
    }
    private DLinkedNode addNodeHead(int key,int value){
        DLinkedNode node = new DLinkedNode(key,value);
        moveNodeToHeadHelper(node);
        dLinkSize++;
        return node;
    }
    private void moveNodeToHead(DLinkedNode node){
        removeNode(node);
        moveNodeToHeadHelper(node);
    }
    private int deleteTailNode(){
        int key = tail.prior.key;
        removeNode(tail.prior);
        dLinkSize--;
        return key;
    }
    private void removeNode(DLinkedNode node){
        node.prior.next = node.next;
        node.next.prior = node.prior;
    }
    private void moveNodeToHeadHelper(DLinkedNode node){
        node.next = head.next;
        head.next.prior = node;
        head.next = node;
        node.prior = head;
    }
}

总结: 用hashmap存key和链表节点,双向链表的头代表新的或刚使用的,双向链表的尾代表要删除的。双向链表维护虚拟头结点,虚拟尾结点来统一操作。 要注意put的判断,要先看key在不在map中,而不是先看链表长度是不是小于容量,因为会发生链表长度没到容量,但是map中已经存在key,想要覆盖的情况,这个是我踩过的坑。

posted @ 2024-03-29 20:18  jeasonGo  阅读(32)  评论(0)    收藏  举报