这个题目leetcode里也有,因为要满足1)快速地get 2)与加入时间相关的pop out 两个operations。用python的OrdereDdict实现:
from collections import OrderedDict
class LRUCache:
def __init__(self, capacity):
self._cache = OrderedDict()
self.capacity = capacity
def get(self, key: int) -> int:
if key not in self._cache:
return -1
self._cache.move_to_end(key)
return self._cache[key]
def put(self, key: int, value: int):
self._cache[key] = value
self._cache.move_to_end(key)
if len(self._cache) > self.capacity:
self._cache.popitem(last=False)
Python的OrderedDict一共就多提供了两个接口,popitem()以及 move_to_end() 这个LRU_cache问题中就全用到了。。。
真正用python解决问题的时候,或者是面试时想使用lru_cache,不用麻烦自己去编这个东西,python functools里就有这个,我通常使用decorator形式。下面用最简单的fibonacci问题展示一下:
from functools import lru_cache
class Solution:
@lru_cache(maxsize=None)
def fib(self, n: int) -> int:
if n == 0:
return 0
if n == 1:
return 1
return self.fib(n-1) + self.fib(n-2)
本来递归exponential的复杂度,加了个decorator立马老老实实地回归本来面目成linear,真是不错;而且真的在工程实践的时候,递归的代码通常要清晰很多,所以本来类似的解决方案就很可能是最好选择。有点可惜的是,因为lru_cache底层就是用一个类似OrderedDict的东西实现的,所以它只能被用在函数签名可以被hash的情况下,也是没有办法的事情。不过像我这么喜欢用这个东西的人,是愿意改改函数签名去使用它的。
顺便说一句,因为时刷题或面试,不用考虑内存开销,maxsize直接开成最大就好。