(每天学一道)力扣算法:146题LRU缓存机制
(每天学一道)力扣算法:146题LRU缓存机制(Least Recently Used)
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制 。
实现 LRUCache 类:
•LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存
•int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
•void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
进阶:你是否可以在 O(1) 时间复杂度内完成这两种操作?
1,解题思路(关键字、关键句)
(1)读题得关键信息:容量、get(key)、put(key, value); 写入数据前,容量上限,删除最久未使用数据值,从而腾出空间,最后 O(1):
get(key)、put(key, value)、容量-----联想到键值对的容器,map家族中找。
O(1)--------------------------------------------锁定容器是~哈希表。
▪到这里只用hashMap,只可以往里放键值put,跟从里边取出来值,但是删除规则:写入新数据前先删除比较久未使用后腾出空间来。
(2)(非常隐蔽的线索是:咱存放数据需要有先后的规律,才可以使得取数据,删除数据有规律~例如咱把最新使用的数据放在最前面位置,后边的数据就是比较久的数据~
而hashMap无法满足此隐蔽的规律,因为hashMap存数据是无序的,咱需要再找到一个存取有先后规律的容器:对于有出入问题顺序的容器-----栈、队列、链表
(这里咱选择链表,理由:考虑到O(1)的时间要求,因为栈、队列的操作结点要么是头结点、尾结点的,可是这里咱有可能会出现key的结点在中间位置,不在头尾处,
导致时间不满足O(1)。(链表特点:快速移动结点的位置。))
综上,容器:双向链表+hashMap(实现O(1))
ps:理由如下:
2,本题难点:访问get、插入put时间先后顺序、O(1)时间复杂度
题目要求get、put,更新数据后,该数据需要被设置为最新访问数据,所以需要:
①需要随机访问 ~ 哈希表实现时间复杂度O(1)的随机访问。
②需要把该数据插入到头部或者尾部~双向链表
3,代码实现:
3-1,双向链表结点类(内部类)
3-2,辅助变量:HashMap、容器大小capacity、size、头结点、尾结点
3-3,题意:•LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存
所以咱的构造方法:参数是capacity+顺便初始化一下咱的辅助变量。(其中要结点的指针指向也需要初始化。)
3-4,题意:•int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
缓存结构:双链表+哈希表,值在双向链表的结点里,而咱是通过哈希表键值对(key,value~结点位置),所以需要先通过哈希表get(key)获得结点,
然后判断是否为空,空返回-1,否则要返回值啦,注意返回值前先挪结点到头结点位置哈)
(要注意细节:get过的结点就是最新使用的结点啦!要把它移动到头结点的位置。)
3-5,题意:•void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,
它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
代码答案来着力扣官方答案:链接:https://leetcode-cn.com/problems/lru-cache/solution/lruhuan-cun-ji-zhi-by-leetcode-solution/
ps:面试解题加分技巧
回答完成以上大家都想到的外:添加上:
(注:考虑过以下的实现)(考虑过,不用给出具体实现啦!)
1,线程安全(synchronized method)
2,分布式的LRU
3,High Throughput (CAS操作)
4,考虑过分段锁(ConcurrentHashMap)
5,读写锁(若容忍一定的精度损失)
6,提起分配空间的LRU
7, 中间留空洞的做法
本文来自博客园,作者:一乐乐,转载请注明原文链接:https://www.cnblogs.com/shan333/p/14941165.html