AlgoMooc

LRU 缓存

27 / 28基础内容

数据结构动画

LRU 缓存

加载中
正在加载动画引擎...

本课导读

LRU(最近最少使用)缓存:空间满了就淘汰「最久没被用过」的数据。它用双向链表记录使用顺序、哈希表做 O(1) 定位,两者配合让 get/put 都达到 O(1)。

你将学到
  • 双向链表(头=最近、尾=最久)+ 哈希表(key→节点)
  • get / put 都是 O(1)
  • 每次访问都要把对应元素刷新为「最近」

LRU 是什么(缓存淘汰策略)

想象你有一个小书桌,只能放 3 本书。当你需要一本新书时,如果桌子满了,你会扔掉最久没翻过的那本。这就是 LRU(Least Recently Used) 缓存淘汰策略:当缓存空间满时,优先淘汰最久未被访问的数据。

为什么需要 双向链表+哈希表 两种结构

仅用链表,查找数据需要 O(n) 遍历;仅用哈希表,无法快速调整节点顺序(因为哈希表无序)。双向链表 负责维护访问顺序(最近访问的放头部,最久未用的放尾部),哈希表 负责 O(1) 定位节点。两者配合,才能同时实现快速查找和快速顺序调整。

get 和 put 的完整流程

get(key):从哈希表找节点,若存在则将该节点移到链表头部(表示最近使用),返回 value;否则返回 -1。

put(key, value):若 key 已存在,更新 value 并移到头部;若不存在,创建新节点加入头部,若容量超限,则删除链表尾部节点(最久未用)并同时从哈希表移除。

为什么 get/put 都是 O(1)

  • 哈希表查找、插入、删除都是 O(1)。
  • 双向链表的头部插入、尾部删除、节点移动(删除+插入)都是 O(1),因为只需修改相邻节点的指针,无需遍历。
  • 因此整个操作时间复杂度为 O(1)。

工程实现与面试手写

在 Java 中可使用 LinkedHashMap,设置 accessOrder=true 并重写 removeEldestEntry 即可实现 LRU。Python 中 OrderedDict 的 move_to_end 和 popitem(last=False) 也能轻松实现。面试手写时,通常要求自己实现双向链表和哈希表,以考察对数据结构的理解。

吴师兄提示:哈希表查得快 + 双向链表序得动。

学完练一练

把刚学的结构放进 LeetCode 题里用一次。

去图解题库实战