LeetCode 146. LRU Cache 题解

LeetCode 146. LRU Cache 题解

题目描述

请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。

实现 LRUCache 类:

  • LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1
  • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

示例 1:

复制代码
输入
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出
[null, null, null, 1, null, -1, null, -1, 3, 4]

解题思路

使用双向链表 + 哈希表实现:

  • 双向链表:按使用顺序排列,最近使用的在头部,最久未使用的在尾部
  • 哈希表:快速查找节点

代码实现

python 复制代码
class DLinkedNode:
    def __init__(self, key=0, value=0):
        self.key = key
        self.value = value
        self.prev = None
        self.next = None

class LRUCache:
    def __init__(self, capacity):
        self.cache = dict()  # key -> node
        self.head = DLinkedNode()  # 虚拟头节点
        self.tail = DLinkedNode()  # 虚拟尾节点
        self.head.next = self.tail
        self.tail.prev = self.head
        self.capacity = capacity
        self.size = 0
    
    def get(self, key):
        if key not in self.cache:
            return -1
        # 将访问的节点移到头部
        node = self.cache[key]
        self.moveToHead(node)
        return node.value
    
    def put(self, key, value):
        if key in self.cache:
            # 更新值并移到头部
            node = self.cache[key]
            node.value = value
            self.moveToHead(node)
        else:
            # 创建新节点
            node = DLinkedNode(key, value)
            self.cache[key] = node
            self.addToHead(node)
            self.size += 1
            
            # 超出容量,删除尾部节点
            if self.size > self.capacity:
                removed = self.removeTail()
                del self.cache[removed.key]
                self.size -= 1
    
    def addToHead(self, node):
        node.prev = self.head
        node.next = self.head.next
        self.head.next.prev = node
        self.head.next = node
    
    def removeNode(self, node):
        node.prev.next = node.next
        node.next.prev = node.prev
    
    def moveToHead(self, node):
        self.removeNode(node)
        self.addToHead(node)
    
    def removeTail(self):
        node = self.tail.prev
        self.removeNode(node)
        return node

复杂度分析

  • 时间复杂度:get 和 put 操作都是 O(1)
  • 空间复杂度:O(capacity)

测试案例

python 复制代码
# 测试案例 1
lru = LRUCache(2)
lru.put(1, 1)
lru.put(2, 2)
assert lru.get(1) == 1  # 返回 1
lru.put(3, 3)  # 驱逐 2
assert lru.get(2) == -1  # 返回 -1
lru.put(4, 4)  # 驱逐 1
assert lru.get(1) == -1  # 返回 -1
assert lru.get(3) == 3  # 返回 3
assert lru.get(4) == 4  # 返回 4

总结

本题是 LRU 缓存的经典实现。

关键点:

  • 双向链表维护使用顺序
  • 哈希表实现 O(1) 查找
  • 虚拟头尾节点简化操作
  • 移动节点到头部表示最近使用
  • 删除尾部节点表示逐出最久未使用
相关推荐
hoiii18714 分钟前
孤立森林 (Isolation Forest) 快速异常检测系统
算法
c++之路1 小时前
适配器模式(Adapter Pattern)
java·算法·适配器模式
吴声子夜歌2 小时前
Java——接口的细节
java·开发语言·算法
myheartgo-on2 小时前
Java—方 法
java·开发语言·算法·青少年编程
宝贝儿好3 小时前
【LLM】第三章:项目实操案例:智能输入法项目
人工智能·python·深度学习·算法·机器人
雪碧聊技术4 小时前
上午题_算法
算法·软考·软件设计师
naturerun4 小时前
从数组中删除元素的算法
数据结构·c++·算法
he___H4 小时前
接雨水----解
leetcode
斯内科5 小时前
四胞胎素数:找出‌个位数分别是 1、3、7、9‌,且‌十位及更高位数字完全相同‌的质数,例如 11、13、17、19
算法·质数·素数·四胞胎素数