LRU(最近最少使用)缓存首先丢弃最近最少使用的项目。该算法需要跟踪什么时候使用过,如果想要确保算法总是丢弃最近最少使用的项目,这会很昂贵。该技术的一般实现需要保留缓存行的“年龄位”并根据年龄位跟踪“最近最少使用”的缓存行。
我们的问题陈述是设计和实现最近最少使用 (LRU) 缓存的数据结构。
它应该支持以下操作:get 和 put。
* get(key) – 如果键存在于缓存中,则获取键的值(将始终为正),否则返回 -1。
* put(key, value) – 如果键不存在,则设置或插入值。当缓存达到其容量时,它应该在插入新项目之前使最近最少使用的项目无效。
缓存总是以正容量初始化。
例子:
Input/Output :
LRUCache cache = new LRUCache( 2 /* capacity */ );
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // returns 1
cache.put(3, 3); // evicts key 2
cache.get(2); // returns -1 (not found)
cache.put(4, 4); // evicts key 1
cache.get(1); // returns -1 (not found)
cache.get(3); // returns 3
cache.get(4); // returns 4
我们的解决方案是使用集合模块中 OrderedDict 的强大功能,它保持键的插入顺序,如果需要,我们可以更改该顺序。最好的部分是所有操作的时间复杂度都是 O(1)。
我们以这样一种方式维护我们的 OrderedDict,即订单显示它们最近被使用的时间。一开始,我们将有最近最少使用的,最后是最近使用的。
如果对键进行任何更新或查询,它会移动到末尾(最近使用过)。如果添加了任何内容,则在最后添加(最近使用/添加)
对于 get(key):我们返回在 O(1) 中查询的键的值,如果在 out dict/cache 中没有找到键,则返回 -1。并且还将钥匙移到最后以显示它最近被使用过。
对于 put(key, value):首先,我们通过常规方法添加/更新键。并且还将钥匙移到最后以显示它最近被使用过。但是这里我们也会检查我们有序字典的长度是否超过了我们的容量,如果是,我们删除第一个键(最近最少使用)
Python3
from collections import OrderedDict
class LRUCache:
# initialising capacity
def __init__(self, capacity: int):
self.cache = OrderedDict()
self.capacity = capacity
# we return the value of the key
# that is queried in O(1) and return -1 if we
# don't find the key in out dict / cache.
# And also move the key to the end
# to show that it was recently used.
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]
# first, we add / update the key by conventional methods.
# And also move the key to the end to show that it was recently used.
# But here we will also check whether the length of our
# ordered dictionary has exceeded our capacity,
# If so we remove the first key (least recently used)
def put(self, key: int, value: int) -> None:
self.cache[key] = value
self.cache.move_to_end(key)
if len(self.cache) > self.capacity:
self.cache.popitem(last = False)
# RUNNER
# initializing our cache with the capacity of 2
cache = LRUCache(2)
cache.put(1, 1)
print(cache.cache)
cache.put(2, 2)
print(cache.cache)
cache.get(1)
print(cache.cache)
cache.put(3, 3)
print(cache.cache)
cache.get(2)
print(cache.cache)
cache.put(4, 4)
print(cache.cache)
cache.get(1)
print(cache.cache)
cache.get(3)
print(cache.cache)
cache.get(4)
print(cache.cache)
#This code was contributed by Sachin Negi
OrderedDict([(1, 1)])
OrderedDict([(1, 1), (2, 2)])
OrderedDict([(2, 2), (1, 1)])
OrderedDict([(1, 1), (3, 3)])
OrderedDict([(1, 1), (3, 3)])
OrderedDict([(3, 3), (4, 4)])
OrderedDict([(3, 3), (4, 4)])
OrderedDict([(4, 4), (3, 3)])
OrderedDict([(3, 3), (4, 4)])
时间复杂度:O(1)
LRU的其他实现