返回

LeetCode 146:LRU 缓存机制——巧用哈希表和双向链表

见解分享

LRU 缓存机制简介

LRU(最近最少使用)缓存机制是一种广泛应用于计算机系统中的高速缓存策略,其核心思想是优先淘汰最长时间未被使用的缓存项,从而为新数据腾出空间。

运用哈希表和双向链表实现 LRU 缓存

哈希表和双向链表是实现 LRU 缓存的理想数据结构:

  • 哈希表 :快速查找缓存项并更新其访问时间。
  • 双向链表 :维护缓存项的插入和删除顺序,以便快速淘汰最少使用的项。

哈希表

我们将使用一个哈希表来存储缓存项。键为缓存项的键,值为指向双向链表节点的指针。

HashMap<Integer, Node> cache;

双向链表

双向链表中的每个节点存储一个缓存项及其访问时间。节点通过 prevnext 指针连接。

class Node {
    int key;
    int value;
    Node prev;
    Node next;
    public Node(int key, int value) {
        this.key = key;
        this.value = value;
    }
}

LRU 缓存实现

class LRUCache {
    private int capacity;
    private HashMap<Integer, Node> cache;
    private Node head, tail;

    public LRUCache(int capacity) {
        this.capacity = capacity;
        cache = new HashMap<>();
        head = new Node(-1, -1);
        tail = new Node(-1, -1);
        head.next = tail;
        tail.prev = head;
    }

    public int get(int key) {
        Node node = cache.get(key);
        if (node == null) return -1;
        removeNode(node);
        addToHead(node);
        return node.value;
    }

    public void put(int key, int value) {
        Node node = cache.get(key);
        if (node != null) {
            removeNode(node);
            node.value = value;
        } else {
            node = new Node(key, value);
            cache.put(key, node);
            if (cache.size() > capacity) {
                Node last = tail.prev;
                removeNode(last);
                cache.remove(last.key);
            }
        }
        addToHead(node);
    }

    private void addToHead(Node node) {
        node.next = head.next;
        node.prev = head;
        head.next.prev = node;
        head.next = node;
    }

    private void removeNode(Node node) {
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }
}

算法分析

  • 时间复杂度:
    • get()put() 操作均为 O(1)。
  • 空间复杂度: O(capacity),因为哈希表最多存储 capacity 个缓存项。

总结

通过巧妙运用哈希表和双向链表,我们高效地实现了 LRU 缓存机制。该实现具备良好的时间和空间复杂度,适用于各种需要缓存管理的场景。