Leetcode 146. LRU Cache

28 篇文章 0 订阅
15 篇文章 0 订阅

问题描述:实现LRU缓存算法。

题目来源:146. LRU Cache

这个是一种缓存策略以及页面置换淘汰策略。简单的来说就是最近使用的不淘汰,最近没有使用的就要被淘汰。

题目要求put\set都要实现常数时间的操作,则很容易想到利用哈希去做,但是如何来定义最远没有使用的呢?
1、加时间戳(timestamp),但是这样维护时间戳排序的时候很麻烦,时间复杂度很高
2、利用链表来维护当前的节点状态,每当有节点被唤醒的时候插入到头部,每当有新节点插入的时候去掉尾部的节点,双向链表可以实现这个功能,但是双向链表访问到某个节点时仍然有一个线性时间存在,所以再利用一个哈希表来存储每个节点。

结构图

明确一下几点:
  • 1、当get的时候,如果key已经存在,需要把该key节点移位到头部,保持最新,如果不存在返回-1.
  • 2、当put的时候,如果key不在里面,就直接插入到头结点,并检查时候超过最大存储容量,如果超过就剔除最后一个节点。
  • 3、put的时候,如果key在里面,则需要找到key的位置,并将其重新插入到头部,当中有断链、连链的操作,是链表的基本操作。

代码实现如下:

class Node:
    def __init__(self,x):
        self.val = x
        self.prev = None
        self.next = None


class LRUCache:

    def __init__(self, capacity):
        """
        :type capacity: int
        """
        self.hash_map = {}
        self.capacity = capacity
        self.head = Node(None)
        self.tail = Node(None)
        self.head.prev = None
        self.tail.next = None
        self.head.next = self.tail
        self.tail.prev = self.head
        self.node_hm = {}
        

    def get(self, key):
        """
        :type key: int
        :rtype: int
        """
        if self.hash_map.get(key)!=None:
            self.put(key,self.hash_map.get(key))  #更新操作如果在里面的话
            return self.hash_map.get(key)
        else:
            return -1
        
        

    def put(self, key, value):
        """
        :type key: int
        :type value: int
        :rtype: void
        
        tail--head
        """
        
        if self.hash_map.get(key) != None:
                #更新到头结点 无论是否超过容量
                # p = self.head.next
                p = self.node_hm.get(key)
                tmp = self.head.next
                if tmp != p:
                    p.next.prev = p.prev  #连接左边的点
                    p.prev.next = p.next

                    p.prev = self.head  #把p的前驱给head
                    self.head.next = p

                    p.next = tmp  #后驱给下个节点
                    tmp.prev = p

                self.hash_map[key] = value
                self.node_hm[key] = p
        else:
            n = Node(key)
            #如果没有超过容量,插入到头节点
            tmp = self.head.next
            
            self.head.next = n
            n.prev = self.head
            
            tmp.prev = n  #左边两个链
            n.next = tmp
            #此时是最大容量,需要删减
            
            self.hash_map[key] = value
            self.node_hm[key] = n
            # print(self.hash_map)
            if len(self.hash_map) > self.capacity:
                lastNode = self.tail.prev
                lastNode.prev.next = self.tail #链接断链
                self.tail.prev = lastNode.prev  #后指
                
                
                self.hash_map.pop(lastNode.val)  #弹出字典
                self.node_hm.pop(lastNode.val)  #弹出字典
                # del lastNode

参考来源:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值