当前位置: 面试刷题>> LRU 缓存(经典算法150题)
### LRU 缓存机制
**题目描述**:
设计并实现一个 LRU(最近最少使用)缓存机制。该机制将允许你获取和设置键值对,并且会在每次访问(无论是获取还是设置)后更新键的顺序,使得最近使用的键总是排在最前面。如果缓存容量已满,则应当移除最久未使用的键(即最末尾的键)。
**示例**:
- 缓存容量 `capacity` = 2
- 操作序列:
1. `cache.put(1, 1)`
2. `cache.put(2, 2)`
3. `cache.get(1)` // 返回 1
4. `cache.put(3, 3)` // 该操作会使键 2 作废
5. `cache.get(2)` // 返回 -1 (未找到)
6. `cache.get(3)` // 返回 3
7. `cache.put(4, 4)` // 该操作会使键 1 作废
8. `cache.get(1)` // 返回 -1 (未找到)
9. `cache.get(3)` // 返回 3
10. `cache.get(4)` // 返回 4
**要求**:
- `get(key)` 方法应返回键对应的值,如果键不存在则返回 -1。
- `put(key, value)` 方法应插入或更新键的值。如果缓存达到其容量,则应该在插入新项之前使最近最少使用的项无效。
### PHP 实现
```php
class LRUCache {
private $capacity;
private $cache;
private $keys;
function __construct($capacity) {
$this->capacity = $capacity;
$this->cache = [];
$this->keys = new SplDoublyLinkedList();
}
function get($key) {
if (!$this->keys->contains($key)) {
return -1;
}
// 移除旧的节点
$this->keys->offsetUnset($key);
// 添加到头部(最近使用)
$this->keys->offsetSet(0, $key);
return $this->cache[$key];
}
function put($key, $value) {
if ($this->keys->contains($key)) {
// 如果键已存在,先移除旧的
$this->keys->offsetUnset($key);
}
// 添加新值
$this->cache[$key] = $value;
// 添加到头部(最近使用)
if ($this->keys->count() >= $this->capacity) {
// 移除最久未使用的项
$oldestKey = $this->keys->bottom();
$this->keys->offsetUnset($oldestKey);
unset($this->cache[$oldestKey]);
}
$this->keys->offsetSet(0, $key);
}
}
```
注意:PHP 标准库中并没有直接支持双向链表的类,这里为了演示方便,使用了 `SplDoublyLinkedList` 类来模拟键的顺序,但请注意,它并不直接支持通过值来快速移除节点,因此这里的 `contains` 和 `offsetUnset` 方法仅用于示意,实际实现中可能需要额外的数据结构或逻辑来优化。
### Python 实现
```python
from collections import OrderedDict
class LRUCache:
def __init__(self, capacity: int):
self.cache = OrderedDict()
self.capacity = capacity
def get(self, key: int) -> int:
if key not in self.cache:
return -1
else:
# 将访问的键值对移动到最前面
self.cache.move_to_end(key)
return self.cache[key]
def put(self, key: int, value: int) -> None:
if key in self.cache:
# 如果键已存在,先移除旧的
del self.cache[key]
elif len(self.cache) >= self.capacity:
# 移除最久未使用的项
self.cache.popitem(last=False)
# 插入新键值对到最前面
self.cache[key] = value
```
### JavaScript 实现
```javascript
class LRUCache {
constructor(capacity) {
this.capacity = capacity;
this.cache = new Map();
}
get(key) {
if (!this.cache.has(key)) {
return -1;
}
// 移除旧的节点
const value = this.cache.get(key);
this.cache.delete(key);
// 添加到头部(最近使用)
this.cache.set(key, value);
return value;
}
put(key, value) {
if (this.cache.has(key)) {
// 如果键已存在,先移除旧的
this.cache.delete(key);
} else if (this.cache.size >= this.capacity) {
// 移除最久未使用的项
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
// 插入新键值对
this.cache.set(key, value);
}
}
```
以上代码分别用 PHP、Python 和 JavaScript 实现了 LRU 缓存机制,每种语言都利用了其内置的数据结构来优化操作效率。