返回

LeetCode 146:LRU缓存机制之双剑合璧,巧破难题

前端

导语:

大家好,欢迎来到LeetCode刷题打卡系列的第146期。今天我们要挑战的是一道经典的算法问题——LRU缓存机制。LRU(Least Recently Used)缓存是一种常见的缓存策略,它根据数据的最近使用情况来决定哪些数据应该被缓存,哪些数据应该被淘汰。

题目

设计一个LRU缓存机制,该缓存机制的大小为capacity。当缓存机制达到其容量时,它应该以最近最少使用的数据来替换新的数据。

解决方案:

为了解决这个问题,我们需要用到两种数据结构:哈希表和双链表。哈希表可以让我们在O(1)的时间复杂度内查找和插入数据,而双链表可以让我们在O(1)的时间复杂度内删除和插入数据。

思路:

  1. 使用哈希表来存储键值对。哈希表的键是数据本身,哈希表的值是数据在双链表中的节点。
  2. 使用双链表来记录数据的最近使用情况。双链表的头部是最近使用的元素,双链表的尾部是最久未使用的数据。
  3. 当需要将一个新的数据插入到缓存中时,首先检查哈希表中是否存在该数据。如果存在,则将该数据移动到双链表的头部。如果不存在,则将该数据插入到双链表的头部,并将双链表的尾部的数据删除。
  4. 当缓存达到其容量时,则将双链表尾部的数据删除。

代码实现:

class LRUCache {

    private int capacity;
    private HashMap<Integer, Node> map;
    private Node head;
    private Node tail;

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

    public int get(int key) {
        if (!map.containsKey(key)) {
            return -1;
        }
        Node node = map.get(key);
        moveToHead(node);
        return node.value;
    }

    public void put(int key, int value) {
        if (map.containsKey(key)) {
            Node node = map.get(key);
            node.value = value;
            moveToHead(node);
        } else {
            Node node = new Node(key, value);
            addToHead(node);
            map.put(key, node);
            if (map.size() > capacity) {
                Node tailNode = tail.prev;
                removeNode(tailNode);
                map.remove(tailNode.key);
            }
        }
    }

    private void moveToHead(Node node) {
        removeNode(node);
        addToHead(node);
    }

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

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

    private class Node {

        int key;
        int value;
        Node prev;
        Node next;

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

结语:

LRU缓存机制是一个非常经典的算法问题,也是面试中经常遇到的问题。通过这篇文章,我们学习了如何使用哈希表和双链表来实现LRU缓存机制。我希望这篇文章对大家有所帮助,也希望大家能够在LeetCode刷题打卡系列中有所收获。

参考文献:

LeetCode 146. LRU Cache