【每日一题】460.LFU缓存

2020.04.05
今天的题目是一道设计类的题目。和146题LRU缓存机制很类似。并且在解题的设计思路上我确实借鉴了设计思路。
在这里插入图片描述这一类的题目难点都是在存储机制存储满以后如何实现在 O ( 1 ) O(1) O(1)的时间复杂度里面删除元素。
LRU删除元素的操作顺序是删除最久没有使用的,因此采用链表的形式,每次删除头节点就可以。
LFU是删除频次最低的,同频次下删除最久没使用的,因此我们需要得到最低频次的数据是哪些。

设计思路是,字典+双向链表,链表存储一个有序字典和对应的频率数值。

每次进行操作,都将该键值对移动到象征更高频次的节点的有序字典的末尾进行存储。

在进行删除操作时,得到用户的头节点也就是象征最低访问频次的节点,删除该节点中有序字典的头一个键值对即可。

代码如下:

class Listnode():
    def __init__(self, fre = None):
        self.num = fre
        self.dic = collections.OrderedDict()
        self.next = None
        self.pre = None


class LFUCache(object):

    def __init__(self, capacity):
        """
        :type capacity: int
        """
        self.dic = {}
        self.star = Listnode(0)
        self.end = Listnode(float('inf'))
        self.star.next = self.end
        self.end.pre = self.star
        self.capacity = capacity
    
    def move(self, node, key): # 频率加一
        if node.next.num == node.num + 1:
            node.next.dic[key] = node.dic[key]
            node.dic.pop(key)
            self.dic[key] = node.next
        else:
            new_node = Listnode(node.num+1)
            new_node.next = node.next
            node.next.pre = new_node
            new_node.pre = node
            node.next = new_node
            new_node.dic[key] = node.dic[key]
            node.dic.pop(key)
            self.dic[key] = new_node
        if len(node.dic) == 0:
            node.pre.next = node.next
            node.next.pre = node.pre

    def delet(self): # 删除最低使用频次的节点
        node = self.star.next
        #if len(node.dic) == 0:
        #    return
        if len(node.dic) == 1:
            self.star.next = node.next
            node.next.pre = self.star
            [key, value] = node.dic.popitem(last=False)
        else:
            [key, value] = node.dic.popitem(last=False)
        return key

    def get(self, key):
        """
        :type key: int
        :rtype: int
        """
        if key not in self.dic:
            return -1
        node = self.dic[key]
        value = node.dic[key]
        self.move(node, key)
        return value
        

    def put(self, key, value):
        """
        :type key: int
        :type value: int
        :rtype: None
        """
        #三种情况:1.在册,2.不在册未满员,3.不在册,且满员
        if key in self.dic:
            node = self.dic[key]
            node.dic[key] = value
            self.move(node, key)
        else:
            if self.capacity == 0:
                return 
            if len(self.dic) == self.capacity:
                delkey = self.delet()
                print(delkey)
                self.dic.pop(delkey)
            if self.star.next.num == 1:
                node = self.star.next
                node.dic[key] = value
                self.dic[key] = node
            else:
                node = Listnode(1)
                self.star.next.pre = node
                node.next = self.star.next                 
                self.star.next = node
                node.pre = self.star
                self.dic[key] = node
                node.dic[key] = value
# Your LFUCache object will be instantiated and called as such:
# obj = LFUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值