带TTL的LRU缓存的实现-字节手撕-26/10/19

1.普通LRU实现

原题链接:LRU 缓存

python 复制代码
class Node:
    __slots__ = "prev", "next", "key", "value"
    def __init__(self, key = 0, value = None):
        self.key = key
        self.value = value

class LRUCache:
    def __init__(self, c):
        self.c = c
        self.h = {}
        self.dummy = Node()
        self.dummy.next = self.dummy
        self.dummy.prev = self.dummy

    def _remove(self, x):
        x.prev.next = x.next
        x.next.prev = x.prev

    def _put_front(self, x):
        x.next = self.dummy.next
        x.prev = self.dummy
        self.dummy.next.prev = x
        self.dummy.next = x

    def _get_node(self, key):
        if key not in self.h:   return None
        x = self.h[key]
        self._remove(x)
        self._put_front(x)
        return x
    
    def get(self, key):
        x = self._get_node(key)
        return x.value if x else -1

    def put(self, key, value):
        x = self._get_node(key)
        if x is not None:
            x.value = value
            self._remove(x)
            self._put_front(x)
        else:
            x = Node(key, value)
            self.h[key] = x
            self._put_front(x)
            if len(self.h) > self.c:
                back = self.dummy.prev
                del self.h[back.key]
                self._remove(back)

对于实现的方法,我一般采取记忆方式防止漏写(比如_get_node中漏写return x等),下面数字代表几行代码哈哈哈哈。

  • 复杂的方法共两个,_get_node()和_put()
  • _get_node():要记住 1(不在的情况) + 4 (在的情况)
  • put(): 要记住3(不在的情况) + 3(在的情况) + 3(超容量的情况)

2.带TTL的LRU缓存

python 复制代码
import time
class Node:
    __slots__ = "prev", "next", "key", "value", "expire_time"
    def __init__(self, key = 0, value = None, expire_time = 0):
        self.key = key
        self.value = value
        self.expire_time = expire_time

class LRUCache:
    def __init__(self, c, ttl):
        self.c = c
        self.ttl = ttl
        self.h = {}
        self.dummy = Node()
        self.dummy.next = self.dummy
        self.dummy.prev = self.dummy

    def _remove(self, x):
        x.prev.next = x.next
        x.next.prev = x.prev

    def _put_front(self, x):
        x.next = self.dummy.next
        x.prev = self.dummy
        self.dummy.next.prev = x
        self.dummy.next = x
    # 新增一个函数
    def _is_expired(self, x):
        return time.time() > x.expire_time

    def _get_node(self, key):
        if key not in self.h:
            return None
        x = self.h[key]
        if self._is_expired(x):
            del self.h[key]
            self._remove(x)
            return None
        self._remove(x)
        self._put_front(x)
        return x

    def get(self, key):
        x = self._get_node(key)
        return x.value if x else -1
    # 直接踢出末端的实现,几乎和普通LRU一致
    def put(self, key, value):
        x = self._get_node(key)
        if x:
            x.value = value
            x.expire_time = time.time() + self.ttl  # 就多了这一行
            self._remove(x)
            self._put_front(x)
        else:
            x = Node(key, value, time.time() + self.ttl)
            self.h[key] = x
            self._put_front(x)
            if len(self.h) > self.c:
                back = self.dummy.prev
                del self.h[back.key]
                self._remove(back)
                
    # 先踢出过期的,如果没有踢出末端
    def put(self, key, value):
        x = self._get_node(key)
        if x:
            x.value = value
            x.expire_time = time.time() + self.ttl
            self._remove(x)
            self._put_front(x)
        else:
            x = Node(key, value, time.time() + self.ttl)
            self.h[key] = x
            self._put_front(x)
            if len(self.h) > self.c:
                cur = self.dummy.prev
                flag = False
                while cur != self.dummy:
                    if self._is_expired(cur):
                        del self.h[cur.key]
                        self._remove(cur)
                        flag = True
                        break
                    cur = cur.prev
                if not flag:
                    back = self.dummy.prev
                    del self.h[back.key]
                    self._remove(back)

同理,只要我们学会了普通LRU

  • _get_node():要记住 1(不在的情况) + 4 (在的情况) + 4(处理过期的情况)
  • 第1个put(): 要记住4(不在的情况) + 3(在的情况) + 3(超容量的情况)
  • 第2个put():要记住4(在的情况,多一个过期) + 3(不在的情况) + 3(超容量的情况2) + 超容量的情况1
相关推荐
糖果豆豆1 小时前
n log n 到底从哪来?排序下界、2-SAT 与 3-SAT、停机问题,卡的是同一件事
算法·架构
地平线开发者1 小时前
【玩转 征程6 算法工具链:PTQ 工具篇】hb_verifier
算法·自动驾驶
171320330计算机毕设编程1 小时前
计算机毕业设计 基于springboot+vue的在线观鸟视频播放网站 LW PPT
java·大数据·vue.js·spring boot·算法·课程设计
himobrinehacken2 小时前
位运算揭秘:左右移与符号位陷阱
c语言·c++·算法·安全
INGNIGHT2 小时前
815 · 课程表IV(dfs)
算法·深度优先
Pniubi3 小时前
力扣146.LRU缓存机制
算法·leetcode·缓存
云上工程笔记3 小时前
2026年7B到67B模型训练与推理GPU配置评测:LoRA、量化与全量微调对比
人工智能·算法·机器学习
softlgh3 小时前
鼾声识别:嵌入式离线鼾声检测 SDK 与睡眠健康数据
算法·智能家居·智能音箱·鼾声识别·智能枕头·打呼噜
了了3 小时前
图搜索基础学习笔记
算法