leetcode hot100 LRU缓存

146. LRU 缓存

已解答

中等

相关标签

相关企业

请你设计并实现一个满足  LRU (最近最少使用) 缓存 约束的数据结构。

实现 LRUCache 类:

  • LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
  • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。

class ListNode(object):

    def __init__(self,key,val,next=None,prev=None):

        self.val =val

        self.key = key

        self.next = next

        self.prev = prev



 

class LRUCache(object):

    def __init__(self, capacity):

        """

        :type capacity: int

        """

        self.capacity = capacity

        self.head = ListNode(-1,-1,None,None)

        self.tail = ListNode(-1,-1,None,None)

        self.head.next=self.tail

        self.tail.prev = self.head

        self.num_nodes = 0

        self.hashmap={}

        # 应该是保存key :node node里面是val

    def remove_to_tail(self,rt):

        rt.prev.next = rt.next

        rt.next.prev = rt.prev

       

        # 放到末尾,这里有点问题,应为删除的可能就是末尾

        prev = self.tail.prev

        prev.next = rt

        rt.next = self.tail

        self.tail.prev = rt

        rt.prev = prev

    def get(self, key):

        """

        :type key: int

        :rtype: int

        """

        # 转移到链表的尾部

        rt = self.hashmap.get(key,-1)

        if rt==-1:

            # 找不到的话,那就return -1

            return -1

        else:

            # 能找到就找到并且放到末尾

            # 删除原本的,然后放到末尾

            #  如果是末尾的话,根本不用动

            if rt==self.tail.prev:

                return rt.val

            else:

                # 删除原本的

                self.remove_to_tail(rt)

                return rt.val

       

    def put(self, key, value):

        """

        :type key: int

        :type value: int

        :rtype: None

        """

        if  self.hashmap.get(key):

            # print(1111111)

            self.hashmap[key].val = value

            # 然后放到tail去

            rt = self.hashmap[key]

            # 删除原本的

            self.remove_to_tail(rt)


 

        else:

            temp = ListNode(key,value)

            if self.num_nodes<self.capacity:

                self.hashmap[key]=temp

               

               

                prev = self.tail.prev

                prev.next = temp

                temp.next = self.tail

                self.tail.prev = temp

                temp.prev = prev

                self.num_nodes+=1

            else:

                # >=cap,也就是需要我们来删除一个

                # 删除头结点的下一个节点

                dele = self.head.next

                self.head.next = dele.next

                dele.next.prev = self.head

                # hashmap里面也要删除

                # print(self.hashmap)

                # print(dele.key)

                del self.hashmap[dele.key]

                # 删除之后加上最新的到为节点

                self.hashmap[key]=temp

                prev = self.tail.prev

                prev.next = temp

                temp.next = self.tail

                self.tail.prev = temp

                temp.prev = prev

                # 如果input的是相同的key会覆盖掉,这个时候num_nodes-1

                if key == dele.key:

                    self.num_nodes-=1






 

       


 

# Your LRUCache object will be instantiated and called as such:

# obj = LRUCache(capacity)

# param_1 = obj.get(key)

# obj.put(key,value)

这里我们的思路是,放入需要o1那么直接的我们使用hashmap,key是key value是list节点,同时节点要存储key和value,因为要通过节点进行删除,如果只有value,那就无法再hashmap之中删除

根据LRU的规律我们选择双向链表,因为单向的没有prev和next,无法进行删除操作

需要对于LRU算法非常熟悉才行啊,比如说

插入的时候:

        如果没到存储上限,那就直接放到最近使用

        如果到达存储上限,那就删除掉最远的,放到最近使用

        如果插入的是已经有的,那就把原本的换成现在的,并且放到最近使用

查询:

        如果查询到了,把原本节点删除,新节点直接放到最近使用

一些细节:必须要有两个伪装节点head tail因为如果这两个不单独创建的话,删除的时候tail很可能被删除,不好写

class Node(object):
    def __init__(self,key=0,val=0,prev=None,next=None):
        self.key = key
        self.val = val
        self.prev = prev
        self.next = next



class LRUCache:

    def __init__(self, capacity: int):
        self.capacity = capacity
        self.hashmap={}
        self.dummy = Node(0,0)
        self.dummy.prev = self.dummy
        self.dummy.next = self.dummy

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

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


    def get(self, key: int) -> int:
        if self.hashmap.get(key)==None:
            return -1
        else:
            # 先remove然后让道最前面
            # 然后返回
            self.remove(self.hashmap.get(key))
            self.pushfront(self.hashmap.get(key))
            return self.hashmap.get(key).val


        

    def put(self, key: int, value: int) -> None:
        if self.hashmap.get(key)==None:
            # 如果没有,那么就直接pushfront,然后放到hashmap里面
            tmp = Node(key,value)
            self.pushfront(tmp)
            self.hashmap[key] = tmp

            # 如果超出了cap那么删除最后一个

            if len(self.hashmap.keys())>self.capacity:
                tmp = self.dummy.prev
                del self.hashmap[tmp.key]
                self.remove(self.dummy.prev)
        else:
            # 如果有的话,那么就直接的把他在hashmap里面更新然后remove然后放到最前main
            self.hashmap[key].val = value

            self.remove(self.hashmap.get(key))
            self.pushfront(self.hashmap.get(key))
            return 


# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)

思路还是一致的优化一下算法,remove和pushfront单独拿出来作为函数,然后只需要一个dummy节点就行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值