实现一个 LRU 缓存,支持 get 和 put 操作。
面试宝典
2023-06-12
Web前端开发工程师
30
LRU 缓存是一种常见的缓存算法,它是 Least Recently Used 的缩写,意思是删除最近最少使用的缓存。实现 LRU 缓存可以使用哈希表和双向链表的数据结构。
具体实现步骤如下:
1. 定义一个哈希表和一个双向链表。
2. 哈希表用于存储缓存,其中键存储缓存键,值存储链表中相应节点的指针。
3. 双向链表用于存储缓存节点,链表头表示最近使用的缓存,链表尾表示最近未使用的缓存。
4. get操作:如果键存在于哈希表中,则将对应节点移动到链表头并返回节点值,否则返回 -1。
5. put操作:如果键存在于哈希表中,则将对应节点的值更新,将节点移到链表头。
6. 如果键不存在于哈希表中,首先创建一个新节点并加入链表头,然后将键和节点指针添加到哈希表中。
7. 如果缓存超过限制,删除链表尾节点,并在哈希表中删除对应键值对。
以下是一个简单的 Python 代码实现:
```python
class LRUCache:
def __init__(self, capacity: int):
self.capacity = capacity
self.cache = {}
self.head = ListNode(0, 0) # 双向链表头
self.tail = ListNode(0, 0) # 双向链表尾
self.head.next = self.tail
self.tail.prev = self.head
def get(self, key: int) -> int:
if key in self.cache:
node = self.cache[key]
self.move_to_head(node)
return node.val
else:
return -1
def put(self, key: int, value: int) -> None:
if key in self.cache:
node = self.cache[key]
node.val = value
self.move_to_head(node)
else:
node = ListNode(key, value)
self.cache[key] = node
self.add_to_head(node)
if len(self.cache) > self.capacity:
tail_node = self.remove_tail()
del self.cache[tail_node.key]
def move_to_head(self, node):
self.remove_node(node)
self.add_to_head(node)
def remove_node(self, node):
node.prev.next = node.next
node.next.prev = node.prev
def add_to_head(self, node):
node.prev = self.head
node.next = self.head.next
self.head.next.prev = node
self.head.next = node
def remove_tail(self):
node = self.tail.prev
self.remove_node(node)
return node
```
在上述代码中,节点类为:
```python
class ListNode:
def __init__(self, key=0, val=0):
self.key = key
self.val = val
self.prev = None
self.next = None
```
时间复杂度分析:
- get: O(1)
- put: O(1) ,若需要删除尾部则最坏为 O(capacity)。
因此,该算法的时间复杂度为 O(1)。
具体实现步骤如下:
1. 定义一个哈希表和一个双向链表。
2. 哈希表用于存储缓存,其中键存储缓存键,值存储链表中相应节点的指针。
3. 双向链表用于存储缓存节点,链表头表示最近使用的缓存,链表尾表示最近未使用的缓存。
4. get操作:如果键存在于哈希表中,则将对应节点移动到链表头并返回节点值,否则返回 -1。
5. put操作:如果键存在于哈希表中,则将对应节点的值更新,将节点移到链表头。
6. 如果键不存在于哈希表中,首先创建一个新节点并加入链表头,然后将键和节点指针添加到哈希表中。
7. 如果缓存超过限制,删除链表尾节点,并在哈希表中删除对应键值对。
以下是一个简单的 Python 代码实现:
```python
class LRUCache:
def __init__(self, capacity: int):
self.capacity = capacity
self.cache = {}
self.head = ListNode(0, 0) # 双向链表头
self.tail = ListNode(0, 0) # 双向链表尾
self.head.next = self.tail
self.tail.prev = self.head
def get(self, key: int) -> int:
if key in self.cache:
node = self.cache[key]
self.move_to_head(node)
return node.val
else:
return -1
def put(self, key: int, value: int) -> None:
if key in self.cache:
node = self.cache[key]
node.val = value
self.move_to_head(node)
else:
node = ListNode(key, value)
self.cache[key] = node
self.add_to_head(node)
if len(self.cache) > self.capacity:
tail_node = self.remove_tail()
del self.cache[tail_node.key]
def move_to_head(self, node):
self.remove_node(node)
self.add_to_head(node)
def remove_node(self, node):
node.prev.next = node.next
node.next.prev = node.prev
def add_to_head(self, node):
node.prev = self.head
node.next = self.head.next
self.head.next.prev = node
self.head.next = node
def remove_tail(self):
node = self.tail.prev
self.remove_node(node)
return node
```
在上述代码中,节点类为:
```python
class ListNode:
def __init__(self, key=0, val=0):
self.key = key
self.val = val
self.prev = None
self.next = None
```
时间复杂度分析:
- get: O(1)
- put: O(1) ,若需要删除尾部则最坏为 O(capacity)。
因此,该算法的时间复杂度为 O(1)。
相关文章
- PHP中常用的设计模式有哪些?
- 请谈谈您对PHP的垃圾回收机制的了解及实践。
- 请列出与PHP相关的缓存机制及其优缺点。
- 请解释下PHP中会话(session)和Cookie(cookie)的作用。
- 聊一下高并发和高性能的区别和联系?
- 请给一个例子解释一下PHP中的闭包函数是什么?
- 请描述在Golang中使用MongoDB时的最佳实践。
- 请解释HTTP的基本概念,以及在Golang中如何使用HTTP?
- PHP中如何处理文件上传和下载?
- 如何在Golang中进行并发编程?
- 如何在Golang中实现单例模式?
- 请解释一下PHP中的MVC模式是如何工作的?
- 请问PHP中如何实现多线程?
- 请解释什么是defer语句,以及它有什么作用?
- PHP中如何进行单元测试以及如何在开发过程中保证代码质量?
- 在PHP中,Magic Method都有哪些,并举例说明它们的作用?
- PHP7和PHP5的性能上有什么差别?
- 请提供至少三个通过PHP实现的网站性能优化技巧。
- 如何通过PHP来保护您的代码免受SQL注入攻击?
- 请举例说明PHP中如何处理异常?
微信收款码
支付宝收款码