102.LFU缓存
题目链接
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/lfu-cache
题目描述
设计并实现最不经常使用(LFU)缓存的数据结构。它应该支持以下操作:get 和 put。
get(key) - 如果键存在于缓存中,则获取键的值(总是正数),否则返回 -1。
put(key, value) - 如果键不存在,请设置或插入值。当缓存达到其容量时,它应该在插入新项目之前,使最不经常使用的项目无效。在此问题中,当存在平局(即两个或更多个键具有相同使用频率)时,最近最少使用的键将被去除。
进阶:
你是否可以在 O(1) 时间复杂度内执行两项操作?
示例:
LFUCache cache = new LFUCache( 2 /* capacity (缓存容量) */ );
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 去除 key 2
cache.get(2); // 返回 -1 (未找到key 2)
cache.get(3); // 返回 3
cache.put(4, 4); // 去除 key 1
cache.get(1); // 返回 -1 (未找到 key 1)
cache.get(3); // 返回 3
cache.get(4); // 返回 4
重难点
cache数组类型为{value, freq}[]
重点在根据freq更新列表顺序上, 这里使用了findIndex的数组原生方法, 找到第一个小于等于该item.freq的index, 插入即可.
作者:jiang-li-rui
链接:https://leetcode-cn.com/problems/lfu-cache/solution/yuan-sheng-shu-zu-fei-o1ban-ben-by-jiang-li-rui/
题目分析
- 这道题我真不会,看了解析以后,嗯,还是困难,查了相关知识点,努力理解。
- cache数组类型为{value, freq}[]
重点在根据freq更新列表顺序上, 这里使用了findIndex的数组原生方法, 找到第一个小于等于该item.freq的index, 插入即可。
/** * @param {number} capacity */ var LFUCache = function(capacity) { this.cache = []; this.L = capacity; }; /** * @param {number} key * @return {number} */ LFUCache.prototype.get = function(key,value) { //查找key相同的值 let index = this.cache.findIndex(item=>item.key === key); if(index !== -1){ //如果有值 const item = this.cache[index]; //如果值有更改 if(value) item.value = value; //调用更新函数 this.update(item,index); // 返回该值 return item.value; } return -1; }; /** * 更新策略 * @param {array} item 待更新的元素 * @param {number} idx 索引 * @return {void} */ LFUCache.prototype.update = function(item, idx) { // 如果idx存在, 也就是获取而非添加的情况 if(idx !== undefined){ // 增加其使用频率 item.freq += 1 // 从原数组中删除, 在后续过程中在添加到预定位置 this.cache.splice(idx, 1) } // 获取要插入的位置索引, 找到第一个freq小于等于待插入元素freq的地方 let index = this.cache.findIndex((a, i) => a.freq <= item.freq) // 如果没有找到, 证明所有元素都大于待插入元素, 所以在末尾添加 if(index === -1) { index = this.cache.length } // 在index出添加待插入元素 this.cache.splice(index, 0, item) }; /** * @param {number} key * @param {number} value * @return {void} */ LFUCache.prototype.put = function(key, value) { //长度为0,return 0 if(this.L === 0) return 0; //如果没有获取值 if(this.get(key, value) === -1){ // 如果长度到了限制 if(this.cache.length === this.L) { // 删除最末尾一个(肯定为使用频率最少的) this.cache.pop() } // 插入元素 this.update({key, value,freq: 0}) } }; /** * Your LFUCache object will be instantiated and called as such: * var obj = new LFUCache(capacity) * var param_1 = obj.get(key) * obj.put(key,value) */