leetcode 力扣 146 LRU缓存

77 阅读1分钟

纯编程能力的题,只有编程没有算法,考验是否够细心

哈希表的作用是O(1)时间内检查链表中是否存在某节点

感觉我在put操作比官解更严谨一点?

class LRUCache {

    // 建立双向链表结构
    class DLinkedNode {
        int key;
        int value;
        DLinkedNode pre;
        DLinkedNode next;

        public DLinkedNode() {
        }

        public DLinkedNode(int _key, int _value) {
            key = _key;
            value = _value;
        }
    }

    // 当前节点数量
    private int size;
    // 缓存容量
    private int capacity;
    // 哈希表
    private Map<Integer, DLinkedNode> nodeMap = new HashMap<>();
    // 伪头部,伪尾部
    private DLinkedNode head, tail;

    public LRUCache(int capacity) {
        this.size = 0;
        this.capacity = capacity;
        head = new DLinkedNode();
        tail = new DLinkedNode();
        head.next = tail;
        tail.pre = head;
    }

    public int get(int key) {
        DLinkedNode node = nodeMap.get(key);
        // 如果节点不存在,返回null
        if (node == null) {
            return -1;
        }
        // 存在,把节点移动到头部,返回value
        moveToHead(node);
        return node.value;
    }

    public void put(int key, int value) {
        DLinkedNode node = nodeMap.get(key);

        // 如果key已经存在,更新value
        if (node != null) {
            node.value = value;
            // 移动到头部
            moveToHead(node);
            // 更新哈希表
            nodeMap.put(key, node);

            // key不存在,插入新的node,先检查容量是否越界
        } else if (size == capacity) {
            // 容量不足,移除尾节点,再插入
            DLinkedNode oldTail = removeTail();
            node = new DLinkedNode(key, value);
            // 更新哈希表
            nodeMap.remove(oldTail.key);
            nodeMap.put(key, node);
            addToHead(node);
        } else {
            // 容量足够,直接在头部插入
            node = new DLinkedNode(key, value);
            addToHead(node);
            // 更新哈希表
            nodeMap.put(key, node);
            // 记得更新size
            size++;
        }

    }

    private void moveToHead(DLinkedNode node) {
        if (node.pre != head) {
            // 断开node的前后节点
            node.pre.next = node.next;
            node.next.pre = node.pre;
            // 把node插入头部
            addToHead(node);
        }
    }

    private void addToHead(DLinkedNode node) {
        node.pre = head;
        node.next = head.next;
        node.next.pre = node;
        head.next = node;
    }

    private DLinkedNode removeTail() {
        DLinkedNode oldTail = tail.pre;
        oldTail.pre.next = tail;
        tail.pre = oldTail.pre;
        oldTail.pre = null;
        oldTail.next = null;
        return oldTail;
    }

}

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */