zoukankan      html  css  js  c++  java
  • 【Leetcode刷题】LFU缓存

    题目:https://leetcode-cn.com/problems/lfu-cache/

    思路:

    O(1)的数据结构:hashmap

    维持最近使用:OrderdDict(详见LRU缓存问题)

    使用一个hashmap维系key到出现频率的映射关系

    另一个hashmap维系频率到数据(key-value键值对)的关系

    由于 当存在平局(即两个或更多个键具有相同使用频率)时,应该去除 最近 最少使用的键。因此key-value键值对应该用OrderdDict存储

    import collections
    
    class LFUCache:
        # self.key_fre是key到出现频率的映射关系
        # self.fre_data格式:
        # {
        #     fre1:{
        #         key1:value1,
        #         ...
        #     }
        #     ...
        # }
        def __init__(self, capacity: int):
            self.capacity = capacity
            self.count = 0
            
            self.key_fre = {}
            # 同一频率下,去除最近最少使用的健,退化为LRU缓存问题
            self.fre_data = {}
            self.min_fre = 1
    
        # 更新某一键值对的频率
        def update_fre(self, key, value=None):
            # 需要从self.fre_data中取值
            fre = self.key_fre[key]
            next_fre = fre + 1
            # 从原频率字典删除
            res = self.fre_data[fre].pop(key)
            # 如果当前频率是最小频率,且字典为空,则更新最小频次记录
            if fre == self.min_fre and not self.fre_data[fre]:
                self.min_fre = next_fre
            # 插入下一个频率字典
            if next_fre not in self.fre_data:
                self.fre_data[next_fre] = collections.OrderedDict()
            self.fre_data[next_fre][key] = value if value is not None else res
            # 修改原key与频率的对应关系
            self.key_fre[key] = next_fre
            return res
    
        def get(self, key: int) -> int:
            if key not in self.key_fre:
                return -1
            return self.update_fre(key)
    
        def put(self, key: int, value: int) -> None:
            # capacity还能是0
            if self.capacity == 0:
                return
            # 如果是更新,则要变更key所处频率字典
            if key in self.key_fre:
                self.update_fre(key, value)
            else:
                if self.count >= self.capacity:
                    # 缓存已满,从最小频次字典中pop最少使用的
                    item = self.fre_data[self.min_fre].popitem(last=False)
                    # 删掉对应key与频率的映射关系
                    del self.key_fre[item[0]]
                else:
                    self.count += 1
                # 新加入,更新最小频率
                self.min_fre = 1
                self.key_fre[key] = 1
                if 1 not in self.fre_data:
                    self.fre_data[1] = collections.OrderedDict()
                self.fre_data[1][key] = value
    
  • 相关阅读:
    pdf 转图片,提取图片研究心得
    自己总结 C++ 代码规范
    Sublime Text 配置记录
    iOS控制器之基类设计
    SublimeText配置NodeJS代码提示
    YYCache设计思路及源码学习
    关于近期项目代码整理(iOS)
    iOS中iconfont(图标字体)的基本使用
    容器转场动画
    Xcode7 模拟器安装app (转)
  • 原文地址:https://www.cnblogs.com/luozx207/p/12696107.html
Copyright © 2011-2022 走看看