【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
posted @ 2020-04-14 10:06  luozx207  阅读(446)  评论(0编辑  收藏  举报