双向链表+哈希表
这个设计题蛮有意思的,学到了很多
最近访问的放在前,许久未访问的放在后,同时支持动态空间、末尾删除,顶端插入。第一时间想到双向链表。但是链表不支持O(1)
查询,因此加一个哈希表。
双向链表
指针指向自己代表null,这样的话delete
和insert
操作就不必判空
重载__repr__
方便输出调试
LRU
支持 get
put
方法
get()
使用哈希表取得目标节点的指针,返回键值。同时删除被访问节点并插入表头。 O(1)
put()
先判断是否已经存在于表中,如在表中则修改键值并删除节点插入表头。如不在表内则判断是否满载,如果满载则删除表尾。之后在表头插入新节点。O(1)
maintain()
put()
的子操作。删除表尾。
class LinkedList:
def __init__(self, key = None, val = None, pre = None, nxt = None):
self.key = key
self.val = val
self.pre = self
self.nxt = self
def delete(self):
self.pre.nxt = self.nxt
self.nxt.pre = self.pre
def insert(self, new):
self.nxt.pre = new
new.nxt = self.nxt
self.nxt = new
new.pre = self
def __repr__(self):
return '[key:{:} val:{:} pre:{:} nxt:{:}]'.format(self.key, self.val, self.pre != None, self.nxt != None)
class LRUCache:
def __init__(self, capacity: int):
self.head = LinkedList()
self.capacity = capacity
self.pos = {}
def get(self, key: int) -> int:
if key in self.pos:
cur = self.pos[key]
cur.delete()
self.head.insert(cur)
return cur.val
return -1
def maintain(self):
cur = self.head.pre
cur.delete()
self.pos.pop(cur.key)
def put(self, key: int, value: int) -> None:
if key in self.pos:
self.pos[key].val = value
self.get(key)
else:
if not self.capacity:
self.maintain()
else:
self.capacity -= 1
new = LinkedList(key, value)
self.head.insert(new)
self.pos[key] = new
#print(self.pos)
# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)