LRU (Least Recently Used)
设计LRU缓存结构,该结构在构造时确定大小,假设大小为K,并有如下两个功能
set(key, value):将记录(key, value)插入该结构
get(key):返回key对应的value值
[要求]
set和get方法的时间复杂度为O(1)
某个key的set或get操作一旦发生,认为这个key的记录成了最常使用的。
当缓存的大小超过K时,移除最不经常使用的记录,即set或get最久远的。
若opt=1,接下来两个整数x, y,表示set(x, y)
若opt=2,接下来一个整数x,表示get(x),若x未出现过或已被移除,则返回-1
对于每个操作2,输出一个答案
示例1
输入
[[1,1,1],[1,2,2],[1,3,2],[2,1],[1,4,4],[2,2]],3
返回值
[1,-1]
思路如下:
当我们进行 put 操作的时候:
1.如果要 put已经存在于链表之中了,那么需要把链表中旧的数据删除,然后把新的数据插入到链表的头部
2.如果要 put的数据没有存在于链表之后,需要判断下缓存区是否已满,如果满的话,则把链表尾部的节点删除,之后把新的数据插入到链表头部,如果没有满的话,直接把数据插入链表头部即可
对于 get 操作:
1.如果要 get 的数据存在于链表中,则把 value 返回,并且把该节点删除,删除之后把它插入到链表的头部
2.如果要 get 的数据不存在于链表之后,则直接返回 -1 即可
单链表实现put 和 get 都需要遍历链表查找数据是否存在,所以时间复杂度为 O(n),空间复杂度为 O(1)
# lru design
# @param operators int整型二维数组 the ops
# @param k int整型 the k
# @return int整型一维数组
#
class Solution:
def LRU(self , operators , k ):
# write code here
if not operators:
return []
n = len(operators)
dit_lru = {}
lit_lru = []
ans = []
for i in range(n):
if operators[i][0] == 1:
if operators[i][1] not in lit_lru:
dit_lru[operators[i][1]] = operators[i][2]
lit_lru.append(operators[i][1])
if len(lit_lru)>k:
tmp = lit_lru.pop(0) #列表头为最不常用
dit_lru.pop(tmp) #!!字典中也剔除对应key的item。
else:
lit_lru.remove(operators[i][1])
lit_lru.append(operators[i][1])
dit_lru[operators[i][1]] = operators[i][2]
elif operators[i][0] == 2:
if operators[i][1] not in lit_lru:
ans.append(-1)
else:
lit_lru.remove(operators[i][1])
lit_lru.append(operators[i][1])
ans.append(dit_lru[operators[i][1]])
return ans