【python面试题】LRUCache

下面分 四层 来讲:

一、LRUCache 的"原理"到底是什么?

1️⃣ 先把名字翻译成人话

LRU = Least Recently Used

如果东西太多放不下,就扔掉"最久没用过的"

它不是学术概念,而是非常人类的直觉行为:

• 浏览器缓存

• 手机后台

• 数据库缓存

• CDN

• Redis

• 操作系统页缓存

你每天都在用 LRU,只是没意识到。

2️⃣ LRUCache 解决的是一个非常具体的问题

如何在"有限内存"下,让"最可能再被用到的数据"留得更久?

现实约束:

• 内存有限(不能无限存)

• 访问有"局部性规律"

• 最近用过的东西,大概率马上还会用

这叫 时间局部性(Temporal Locality)

二、为什么"最近使用"是一个好策略?

对比几种"删除策略":

策略 删除谁 问题

FIFO 最早进来的 不管用没用过

Random 随机删 命中率不稳定

LFU 用得最少 维护成本高

LRU 最久没用过 效果好 + 成本低

LRU 是一个:

• 成本可控

• 行为符合直觉

• 命中率高

👉 工程上的"性价比之王"

三、LRUCache 的核心原理(抽象层)

LRU 本质只做三件事:

  1. 快速判断 key 在不在缓存
  2. 每次访问后,标记为"最近使用"
  3. 超容量时,删掉"最久没使用"的

这三点 缺一不可。

四、为什么一定要「dict + 双向链表」?

问题拆解:

1️⃣ 我要 O(1) 查找

👉 用 dict

2️⃣ 我要 O(1) 移动"使用顺序"

👉 用 双向链表

3️⃣ 我要 O(1) 删除最旧的

👉 链表头直接删

4️⃣ 我要 O(1) 找到链表节点

👉 dict[key] → node

这就是为什么结构一定是:

hash map + doubly linked list

不是"巧合",是唯一解之一。

五、LRUCache 的「工程级结构示意」

dict:

key → Node地址

双向链表:

HEAD\] \<-\> \[A\] \<-\> \[B\] \<-\> \[C\] \<-\> \[TAIL

最近使用:靠近 TAIL

最久未用:靠近 HEAD

get(key):

  1. dict 查 node
  2. node 从当前位置摘下
  3. node 插到 tail 前

put(key, value):

如果存在:

更新 value

移到 tail

如果不存在:

新建 node

插到 tail

dict[key] = node

如果超容量:

删除 head.next

六、为什么面试官一定爱考 LRUCache?

这点非常关键。

这道题 不是在考你会不会 LRU

而是在一题里同时考 6 件事:

七、面试官真正想看的能力(重点)

① 你会不会拆需求

"get / put 都是 O(1)"

这是一个强约束

如果你忽略这个条件,直接 list + dict → ❌

② 你知不知道基础数据结构

• hash table

• doubly linked list

不是 API,而是 结构思维

③ 你有没有工程意识

LRU 是:

• 真实存在

• 真正在用

• 不是刷题产物

④ 你会不会组合结构

面试官最爱的一点

不是:

• "背一个结构"

而是:

知道一个结构不够 → 组合两个

⑤ 你对「复杂度」是不是敏感

很多人写得出来

但解释不了:

"为什么这是 O(1)"

你现在问的正是这个点。

⑥ 你能不能解释**"为什么这样设计"**

能写 ≠ 能讲

能讲 ≠ 懂

你现在在往「懂」走。

八、这题在真实世界里"解决了什么"?

举几个真实系统例子:

🔹 浏览器缓存

• 最近访问的页面资源

• 最久不用的图片被清掉

🔹 Redis

• 内存满了

• LRU / LFU 淘汰 key

🔹 数据库

• 查询结果缓存

• 热数据常驻

🔹 操作系统

• 页缓存

• 文件缓存

👉 不是"算法题",是"系统题"

九、面试官最想听的一句话(精华)

你可以直接背:

LRUCache 用来在有限内存下提高缓存命中率,

利用时间局部性原理,

通过哈希表保证 O(1) 查找,

通过双向链表维护访问顺序,

在容量受限时淘汰最久未被访问的数据。

相关推荐
LitchiCheng4 小时前
WSL2 中 pynput 无法捕获按键输入?
开发语言·python
中年程序员一枚4 小时前
Python 中处理视频添加 / 替换音频
开发语言·python·音视频
yuuki2332334 小时前
【C++】模板初阶
java·开发语言·c++
爱吃大芒果4 小时前
Flutter 路由进阶:命名路由、动态路由与路由守卫实现
开发语言·javascript·flutter·华为·ecmascript
世转神风-4 小时前
qt-lambda信号槽机制
开发语言·qt
Katecat996634 小时前
基于YOLO11-C3k2-JDPM的车牌识别系统优化与实现
python
SmoothSailingT4 小时前
C#——单例模式
开发语言·单例模式·c#
与遨游于天地4 小时前
接口与实现分离:从 SPI 到 OSGi、SOFAArk的模块化演进
开发语言·后端·架构
醇氧4 小时前
Spring Boot 应用启动优化:自定义事件监听与优雅启动管理
java·开发语言·python