参考答案:
关于缓存,有个常见的例子是,当用户访问不同站点时,浏览器需要缓存在对应站点的一些信息,这样当下次访问同一个站点的时候,就可以使访问速度变快(因为一部分数据可以直接从缓存读取)。 但是想想内存空间是有限的,所以必须有一些规则来管理缓存的使用,而LRU(Least Recently Used) Cache就是其中之一,直接翻译就是“最不经常使用的数据,重要性是最低的,应该优先删除”。
假设我们要实现一个简化版的这个功能,先整理下需求:
首先题目里很明显的提到了,需要能够标记数据的插入或使用顺序, 所以肯定不能简单使用object实现,需要借助数组,或者es6的Map和Set实现(Map和Set数据遍历是有序的,遍历顺序即插入顺序);
其次需要实现O(1)复杂度,那就也无法用单纯使用数组来实现,所以可以考虑的只有Map和Set,那么最后再考虑下数据重复性的问题,会发现这道题不太需要考虑这个场景,所以我们可以先使用Map来实现。
由于Map的特性是:新插入的数据排在后面,旧数据放在前面, 所以我们只要专注于维持这个逻辑就好了:
接下来就可以一步步是实现代码了,首先是最基本的 构造函数:
1// 第一步代码 2class LRUCache { 3 constructor(n){ 4 this.size = n; // 初始化最大缓存数据条数n 5 this.data = new Map(); // 初始化缓存空间map 6 } 7}
接下来是put方法,put方法要处理3个逻辑:
1、如果待写入的域名,已存在于内存之中,直接更新数据并移动到末尾; 2、如果当前未达到缓存数量上限,直接写入新数据; 3、如果当前已经达到缓存数量上限, 要先删除最不经常使用的数据,再写入数据;
其他都可以直接操作,移动到末尾这个行为,可以拆成"先删除该数据,再从末尾重新插入一条该数据",这样就简单多了。所以我们继续更新代码:
1// 第一步代码 2class LRUCache { 3 constructor(n){ 4 this.size = n; // 初始化最大缓存数据条数n 5 this.data = new Map(); // 初始化缓存空间map 6 } 7 // 第二步代码 8 put(domain, info){ 9 if(this.data.has(domain)){ 10 this.data.delete(domain); // 移除数据 11 this.data.set(domain, info)// 在末尾重新插入数据 12 return; 13 } 14 if(this.data.size >= this.size) { 15 // 删除最不常用数据 16 const firstKey= this.data.keys().next().value; // 不必当心data为空,因为this.size 一般不会取0,满足this.data.size >= this.size时,this.data自然也不为空。 17 this.data.delete(firstKey); 18 } 19 this.data.set(domain, info) // 写入数据 20 } 21}
接着就只剩下get方法了,get方法同样也要处理2种逻辑:
1、根据给定的key,查找是否有对应的信息,若不存在则返回false; 2、若第一步结果存在,则把被访问数据移动到末尾;
1// 第一步代码 2class LRUCache { 3 constructor(n){ 4 this.size = n; // 初始化最大缓存数据条数n 5 this.data = new Map(); // 初始化缓存空间map 6 } 7 8 // 第二步代码 9 put(domain, info){ 10 if(this.data.size >= this.size) { 11 // 删除最不常用数据 12 const firstKey= [...this.data.keys()][0];// 次数不必当心data为空,因为this.size 一般不会取0,满足this.data.size >= this.size时,this.data自然也不为空。 13 this.data.delete(firstKey); 14 } 15 this.data.set(domain, info) // 写入数据 16 } 17 18 // 第三步代码 19 get(domain) { 20 if(!this.data.has(domain)){ 21 return false; 22 } 23 const info = this.data.get(domain); //获取结果 24 this.data.delete(domain); // 移除数据 25 this.data.set(domain, info); // 重新添加该数据 26 return info; 27 } 28}
这一步要稍微注意的是,我们是先移除数据后添加数据,严格遵循最大数量不超过n。
最近更新时间:2024-08-10