leetcode 146

LRU缓存机制

Posted by Static on May 25, 2020

题目链接:https://leetcode-cn.com/problems/lru-cache/

题目描述


分析

1. 双向链表+map

put(): a. 首次添加k和v,会新建节点,添加到双向链表的头结点处(头插法),将k和节点的引用存到map中; b. 若不是首次插入,则通过map找到节点的引用,修改节点的值,再将此节点移到头结点; c. 若容量慢了,则删除尾节点

get(): 要达到O(1),即直接从map中获取,并且此节点移到头结点处


代码实现

public enum Q146 {
    instance;

    static class LRUCache {
        // save k and v
        LinkedNode head;
        LinkedNode tail;

        // save k and LinkedNode's point
        Map<Integer,LinkedNode> map;
        int capacity;

        // Linked's size
        int length;

        public LRUCache(int capacity) {
            if(capacity<=0) throw new Error("capacity is illegal");
            this.capacity=capacity;
            this.map=new HashMap<>(capacity);
            this.head=new LinkedNode();
            this.tail=new LinkedNode();
            // init head and tail
            head.next=tail;
            head.prev=null;
            tail.prev=head;
            tail.next=null;
        }

        public int get(int key) {
            if(map.containsKey(key)){
                LinkedNode node = map.get(key);
                moveToHead(node);
                return node.val;
            }
            return -1;
        }

        private void moveToHead(LinkedNode node) {
            if(node==null||node.prev==head) return;
            LinkedNode prevNode=node.prev;
            prevNode.next=node.next;
            node.next.prev=prevNode;
            node.next=head.next;
            node.prev=head;
            head.next.prev=node;
            head.next=node;
        }

        public void put(int key, int value) {
            if(map.containsKey(key)){
                LinkedNode node = map.get(key);
                node.val=value;
                moveToHead(node);
                return;
            }
            if(length>=capacity){
                LinkedNode removedNode = removeLast();
                if(removedNode!=null){
                    map.remove(removedNode.key);
                }
            }
            map.put(key,addFist(key,value));
        }

        private LinkedNode addFist(int key,int value){
            LinkedNode newNode=new LinkedNode(key,value);
            newNode.next=head.next;
            newNode.prev=head;
            head.next.prev=newNode;
            head.next=newNode;
            length++;
            return newNode;
        }

        private LinkedNode removeLast(){
            if(tail==null||tail.prev==null) return null;
            LinkedNode node=tail.prev.prev;
            if(node!=null){
                LinkedNode removeNode=tail.prev;
               node.next=tail;
               tail.prev=node;
               length--;
               return removeNode;
            }
            return null;
        }
        class LinkedNode {
            public int key;
            public  int val;
            public LinkedNode prev;
            public LinkedNode next;
    
            public LinkedNode(){}
    
            public LinkedNode(int key,int val) {
                this.key=key;
                this.val = val;
            }
        }

    }
    
    // test 
    private void test1(){
        LRUCache lruCache = new LRUCache(3);
        lruCache.put(1,1);
        lruCache.put(2,2);
        lruCache.put(3,3);
        System.out.println(lruCache.get(1));
        // remove 2
        lruCache.put(4,4);
        // -1
        System.out.println(lruCache.get(2));

        lruCache.put(3,6);
        // 6
        System.out.println(lruCache.get(3));
    }

    private void test2(){
        // 4->2
        LRUCache lruCache = new LRUCache(2);
        lruCache.put(2,1);
        lruCache.put(1,1);
        lruCache.put(2,3);
        lruCache.put(4,1);
        // -1
        System.out.println(lruCache.get(1));
        // 3
        System.out.println(lruCache.get(2));
    }
    public static void main(String[] args) {
        Q146.instance.test2();

    }
}