题目
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set.
get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
set(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.
题目要求
要求实现LRU的缓存机制。LRU机制是在缓存溢出时,删除最近最少使用的缓存元素的机制
解题思路
解这道题,我们要考虑LRU的特性。要知道哪些缓存元素是最近被访问过的,哪些已经很久没有访问过了。链表是可以做这件事情的,但是链表删除和替换位置的操作复杂性为 O(n) ,为了优化效率,采用双向链表来存储,但是双向链表的查找复杂度仍为 O(n) ,这时采用哈希表来达到 O(1) 的访问复杂度。每次访问到一个元素,都将该元素移动到链表的头部。当超过缓存限制时,删除链表尾部的元素,同时从哈希表中删除相应的键值。
代码
class Node:
def __init__(self,key,val):
self.val = val
self.key = key
self.next = None
self.pre = None
class DoubleLinkedList:
def __init__(self):
self.header = None
self.tail = None
def add_first(self,node):
if self.header == None:
self.header = node
self.tail = node
else:
h = self.header
self.header = node
node.next = h
h.pre = node
def remove(self,node):
pre,next = node.pre,node.next
if pre:
pre.next = next
else:
self.header = next
if next:
next.pre = pre
else:
self.tail = pre
node.pre = None
node.next = None
def remove_last(self):
if self.tail == None:
return None
tail = self.tail
self.remove(tail)
return tail
class LRUCache(object):
def __init__(self, capacity):
"""
:type capacity: int
"""
self.capacity = capacity
self.count = 0
self.linkedlist = DoubleLinkedList()
self.maps = {}
def get(self, key):
"""
:rtype: int
"""
if key not in self.maps:
return -1
node = self.maps[key]
self.linkedlist.remove(node)
self.linkedlist.add_first(node)
return node.val
def set(self, key, value):
"""
:type key: int
:type value: int
:rtype: nothing
"""
if key not in self.maps:
self.count += 1
node = Node(key,value)
self.maps[key] = node
self.linkedlist.add_first(node)
else:
node = self.maps[key]
node.val = value
self.linkedlist.remove(node)
self.linkedlist.add_first(node)
if self.count > self.capacity:
self.count -= 1
tail = self.linkedlist.remove_last()
del self.maps[tail.key]