题解 | #设计LRU缓存结构#

设计LRU缓存结构

http://www.nowcoder.com/practice/e3769a5f49894d49b871c09cadd13a61

import java.util.*;


class LRUCache {

    // 双向链表的Node,定义key/value以及prev/next指针
    public static class DoubleNode {
        DoubleNode prev;
        DoubleNode next;
        int key;
        int value;

        public DoubleNode(int key, int value) {
            this.key = key;
            this.value = value;
        }

        public DoubleNode() {

        }
    }

    // 缓存的Map,key-key,value-Node<key,value>
    private HashMap<Integer, DoubleNode> cache = new HashMap<>();

    // 双向链表的head
    private DoubleNode head = new DoubleNode();
    // 双向链表的tail
    private DoubleNode tail = new DoubleNode();

    // cache的容量,超过容量直接不允许放入元素了
    int capacity;

    public LRUCache(int capacity) {
        this.capacity = capacity;
        head.next = tail;
        tail.prev = head;
    }

    public int get(int key) {
        DoubleNode node = cache.get(key);
        // 如果缓存中没有的话
        if (node == null) {
            return -1;
        }
        // 如果缓存中有的话,那么移动到head地方去(先从链表中删除再移动)
        removeNode(node);
        addToHead(node);
        return node.value;
    }

    public void put(int key, int value) {
        // 对方法的容量进行判断,筛掉传递非法容量的情况
        if (capacity <= 0) {
            return;
        }
        // 从缓存中根据key拿到node
        DoubleNode node = cache.get(key);
        if (node == null) {
            // 如果缓存的容量已经满了,需要移除掉尾部的节点
            if (cache.size() == capacity) {
                cache.remove(tail.prev.key); // 必须先进行操作,不然tail.prev从链表中移除了,引用找不到了
                removeNode(tail.prev); // 必须后进行操作
            }
            // 到达这里缓存一定没满,需要新创建一个node加入到缓存和双向链表中去
            node = new DoubleNode(key, value);
            cache.put(key, node);
            addToHead(node);
            return;
        }
        // 这部分的逻辑和get是一样的,将node从链表中移除掉,并且加到链表头部去
        removeNode(node);
        addToHead(node);
        // 修改node的value为指定的value
        node.value = value;
    }

    // 将node从双向链表中移除掉,普通的双向链表的删除罢了
    private void removeNode(DoubleNode node) {
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }

    // 将node添加到最前面去(因为head是傀儡节点,所以应该添加到head之后)
    private void addToHead(DoubleNode node) {
        node.next = head.next;
        node.next.prev = node;
        head.next = node;
        node.prev = head;
    }
}

public class Solution {
    /**
     * lru design
     *
     * @param operators int整型二维数组 the ops
     * @param k         int整型 the k
     * @return int整型一维数组
     */
    public int[] LRU(int[][] operators, int k) {
        LRUCache cache = new LRUCache(k);
        List<Integer> ret = new ArrayList<>();
        for (int[] operator : operators) {
            int length = operator.length;
            // 如果是get操作
            switch (length) {
                case 2:
                    int get = cache.get(operator[1]);
                    ret.add(get);
                    break;
                case 3:
                    cache.put(operator[1], operator[2]);
                    break;
            }
        }
        int[] array = new int[ret.size()];
        for (int i = 0; i < array.length; i++) {
            array[i] = ret.get(i);
        }
        return array;
    }
}
全部评论

相关推荐

Java抽象带篮子:难蚌,点进图片上面就是我的大头😆
点赞 评论 收藏
分享
10-14 23:01
已编辑
中国地质大学(武汉) Java
CUG芝士圈:虽然是网上的项目,但最好还是包装一下,然后现在大部分公司都在忙校招,十月底、十一月初会好找一些。最后,boss才沟通100家,别焦虑,我去年暑假找第一段实习的时候沟通了500➕才有面试,校友加油
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务