python
class Node:
__slots__='key','value','next','prev'
def __init__(self,key=0,value=0):
self.key=key
self.value=value
class LRUCache:
def __init__(self,capacity):
self.capacity=capacity
self.key_to_node={}
self.dummy=Node()
self.dummy.next=self.dummy
self.dummy.prev=self.dummy
def get(self,key:int)->int:
if key not in self.key_to_node:
return -1
#在哈希表里面
node=self.key_to_node[key] #拿到节点
self.remove(node) #删除节点
self.push_to_front(node) #移到最前面
return node.value
#新加入节点
def put(self,key:int,value:int):
if key in self.key_to_node: #如果已经存在,就更新value
node=self.key_to_node[key] #拿到节点
node.value=value #更新值
self.remove(node) #在该位置删除元素
self.push_to_front(node) #把更新后的元素移动到最前面
else: #如果节点不在里面,先检查容量,再插入
if len(self.key_to_node)==self.capacity: #容量满了,需要删除最久未使用元素
#删除链表最后一个元素
last=self.dummy.prev #获取链表最后一个元素
self.remove(last) #移除元素
del self.key_to_node[last.key] #哈希表里删除该node
new_node=Node(key,value)
self.push_to_front(new_node) #将新节点放到最前面
self.key_to_node[key]=new_node #加入到哈希表
def remove(self,node): #双链表删除元素操作,双链表断链
node.prev.next=node.next
node.next.prev=node.prev
def push_to_front(self,node): #头插法,将元素放到最前面
node.prev=self.dummy
node.next=self.dummy.next
self.dummy.next.prev=node
self.dummy.next=node
# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)
思路:双链表+哈希表(想象成一堆书,取书放书的过程):因为要求时间复杂度为O(1),所以需要想到使用哈希表;因为要删除某一个元素,可能是中间也可能是两端,所以使用双链表。
步骤:
1.哈希表结构:{key:node},初始化节点node:key,value;初始化双链表,新建哈希表
2.get实现:如果key不在哈希表中,返回-1:若在,则先记录下该节点,然后在原位置删除(remove),再将该节点移动到双链表最前面(push_to_front,因为用过一次,就表示该节点是最新使用的,需要放到最前面),最后返回node.value。
3.put实现:先检查哈希表中是否已经存在,若存在,则先拿到该节点,更新value,再删除该位置的node,并且将node移动到双链表最前面。若不存在,则先检查容量是否满了,满了就先删除双链表最后一个元素:首先拿到双链表最后一个元素,之后删除,然后还需要在哈希表中删除该节点。有了容量之后,存入新节点放到双链表最前面,还需要加入到哈希表中。
4.remove实现:双链表断链操作
5.push_to_front实现:将节点移动到双链表最前面