美文网首页
LeetCode 第146题:LRU缓存机制

LeetCode 第146题:LRU缓存机制

作者: 放开那个BUG | 来源:发表于2020-07-26 22:24 被阅读0次

    1、前言

    题目描述

    2、思路

    所谓的 LRU,指的是,get 某一个 key,如果 key 存在,那么这个 <key,value> 要放到最新的位置。

    如果 set 一个 <key,value>,如果这个 key 已经存在,那么要改变原先 value 的值,并把它放到最新的位置;如果这个 key 不存在,那么先要观察容量满没有,满了则先删除最近不使用的节点,然后将 <key,value> 放到最新位置;否则直接把 <key,value> 放到最新位置。

    3、代码

    import java.util.HashMap;
    import java.util.Map;
    
    class LRUCache {
    
        private Map<Integer, ListNode> map = new HashMap<>();
    
        private ListNode head, last;
    
        private Integer capacity;
    
        public LRUCache(int capacity) {
            this.head = new ListNode(null, null,  -1, -1);
            this.last = new ListNode(null, null, -1, -1);
            head.next = last;
            last.pre = head;
            this.capacity = capacity;
        }
        
        public int get(int key) {
            ListNode node = map.get(key);
            if(node == null){
                return -1;
            }
    
            moveToHead(node);
            return node.value;
        }
        
        public void put(int key, int value) {
            // 有重复的重新赋值并移动到前面即可
            // 如果直接判断大小,很可能出现这种情况:容量为2,{1=1, 2=2},后面再 put(1,3),直接判断会导致 2=2 没了,直接变成了 {1=3}
            ListNode node = map.get(key);
            if(node != null){
                node.value = value;
                moveToHead(node);
                return;
            }
    
            if(map.size() + 1 > capacity){
                ListNode lastNode = removeLast();
                map.remove(lastNode.key);
            }
            node = new ListNode(null, null, key, value);
            map.put(key, node);
            linkHead(node);
        }
    
        /**
         * 将节点链接到最后
         * @param node
         */
        private void linkHead(ListNode node) {
            ListNode nextNode = head.next;
            node.pre = head;
            node.next = nextNode;
            nextNode.pre = node;
            head.next = node;
        }
    
        /**
         * 将最后一个节点去掉
         * @return
         */
        private ListNode removeLast() {
            ListNode lastNode = last.pre;
            //删除节点
            removeNode(lastNode);
            return lastNode;
        }
    
        /**
         * 将要访问的节点移动最前面
         * @param node
         */
        private void moveToHead(ListNode node) {
            // 先删除节点
            removeNode(node);
            linkHead(node);
        }
    
        /**
         * 删除节点
         * @param node
         */
        private void removeNode(ListNode node) {
            ListNode preNode = node.pre;
            ListNode nextNode = node.next;
            preNode.next = nextNode;
            nextNode.pre = preNode;
            node.pre = null;
            node.next = null;
        }
    
        class ListNode {
            ListNode next;
            ListNode pre;
            Integer key;
            Integer value;
    
            public ListNode(ListNode next, ListNode pre, Integer key, Integer value) {
                this.next = next;
                this.pre = pre;
                this.key = key;
                this.value = value;
            }
        }
    
        public static void main(String[] args) {
            LRUCache lRUCache = new LRUCache(2);
            lRUCache.put(1, 1); // 缓存是 {1=1}
            lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
            System.out.println(lRUCache.get(1));    // 返回 1
            lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
            System.out.println(lRUCache.get(2));    // 返回 -1 (未找到)
            lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
            System.out.println(lRUCache.get(1));    // 返回 -1 (未找到)
            System.out.println(lRUCache.get(3));    // 返回 3
            System.out.println(lRUCache.get(4));    // 返回 4
        }
    }
    

    相关文章

      网友评论

          本文标题:LeetCode 第146题:LRU缓存机制

          本文链接:https://www.haomeiwen.com/subject/aynqhktx.html