
1) 【一句话结论】
LRU缓存通过哈希表+双向链表实现,支持O(1)时间访问、插入和淘汰,采用细粒度锁(哈希表查找不加锁,仅操作加锁)保证并发安全,适用于教育系统中课程/习题的快速推荐场景。
2) 【原理/概念讲解】
老师会解释核心数据结构的作用:
tail->prev->next = tail->prev->prev; tail->prev = tail->prev->prev;),无需遍历,时间复杂度为O(1),类比“书架上的书籍,最久未读的从后端直接取下”。3) 【对比与适用场景】
| 策略 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| LRU | 淘汰最久未访问的元素 | 哈希表+双向链表,O(1)访问/插入/淘汰;维护访问顺序 | 教育系统课程推荐(高频课程保留)、习题缓存(高频习题优先) | 需高效数据结构,并发时需加锁 |
| FIFO | 先进先出 | 哈希表+单链表,O(1)插入/淘汰;按时间顺序 | 临时文件缓存(如系统临时文件) | 可能不符合实际访问模式(如刚访问的元素被淘汰) |
| LFU | 淘汰最少使用频率的元素 | 哈希表+频率计数+双向链表,O(1)访问/插入/淘汰;维护频率 | 频繁访问的元素(如高频习题) | 初始阶段计数不准确,需额外数据结构 |
4) 【示例】
用智能指针管理链表节点,避免内存泄漏。伪代码:
#include <unordered_map>
#include <memory>
#include <iostream>
struct Node {
int key;
int value;
std::unique_ptr<Node> prev;
Node* next; // 指向后继节点
};
class LRUCache {
private:
std::unordered_map<int, std::unique_ptr<Node>> cache;
Node* head = new Node(); // 虚拟头节点
Node* tail = new Node(); // 虚拟尾节点
int capacity;
int size;
void addNode(std::unique_ptr<Node> node) {
node->next = head->next;
head->next->prev = node.get();
head->next = node.get();
}
void removeNode(Node* node) {
node->prev->next = node->next;
node->next->prev = node->prev;
}
void moveToHead(std::unique_ptr<Node> node) {
removeNode(node.get());
addNode(std::move(node));
}
public:
LRUCache(int capacity) : capacity(capacity), size(0) {
head->next = tail;
tail->prev = head;
}
int get(int key) {
auto it = cache.find(key);
if (it == cache.end()) return -1;
auto node = std::move(it->second);
moveToHead(std::move(node));
return node->value;
}
void put(int key, int value) {
auto it = cache.find(key);
if (it != cache.end()) {
auto node = std::move(it->second);
node->value = value;
moveToHead(std::move(node));
} else {
if (size == capacity) {
auto tailNode = tail->prev;
removeNode(tailNode);
cache.erase(tailNode->key);
}
auto newNode = std::make_unique<Node>();
newNode->key = key;
newNode->value = value;
moveToHead(std::make_unique<Node>(std::move(newNode)));
cache[key] = std::move(newNode);
size++;
}
}
};
5) 【面试口播版答案】
好的,面试官。我设计的LRU缓存算法核心是哈希表+双向链表结构,保证O(1)时间复杂度的访问、插入和淘汰操作。哈希表用于快速查找元素(相当于索引字典,快速定位课程信息),双向链表维护访问顺序(最近访问的元素放在链表头,最久未访问的放在尾)。当用户访问“数学基础”课程时,若该课程在缓存中,则将其移动到链表头;若未在缓存中,则插入到头并淘汰链表尾的元素(如“物理习题”)。在并发场景下,我会用细粒度锁:哈希表查找操作不加锁(因为只是读取,不修改数据),而插入、删除、移动节点时加锁,确保多线程安全。这样在教育系统中,课程推荐缓存能快速响应高频请求,提升用户体验。
6) 【追问清单】
7) 【常见坑/雷区】