JavaScript算法题实现-146-LRU缓存机制——腾讯面试题库

出题指数(最大5):????

题目

运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put

获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。

写入数据 put(key, value) - 如果密钥已经存在,则变更其数据值;如果密钥不存在,则插入该组「密钥/数据值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。

进阶:

你是否可以在 O(1) 时间复杂度内完成这两种操作?

示例:

LRUCache cache = new LRUCache( 2 /* 缓存容量 */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // 返回  1
cache.put(3, 3);    // 该操作会使得密钥 2 作废
cache.get(2);       // 返回 -1 (未找到)
cache.put(4, 4);    // 该操作会使得密钥 1 作废
cache.get(1);       // 返回 -1 (未找到)
cache.get(3);       // 返回  3
cache.get(4);       // 返回  4

LeetCode原题目指路

题解

LRU缓存机制

Least Recently Used的缩写,即最近最少使用。

原理

选择最近最久未使用的页面予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 t,当须淘汰一个页面时,选择现有页面中其 t 值最大的,即最近最少使用的页面予以淘汰。

假设内存只能容纳3个页大小,按照 7 0 1 2 0 3 0 4 的次序访问页。假设内存按照栈的方式来描述访问时间,在上面的,是最近访问的,在下面的是,最远时间访问的,LRU就是这样工作的。

思路

这个题不涉及复杂的算法,使用栈即可。如果要在O(1)时间内完成,考虑ES6的Map对象。

JavaScript实现

普通版

时间复杂度不一定是O(1)

/**
  * @param {number} capacity
  */
var LRUCache = function (capacity) {
  this.capacity = capacity;
  // 存放key的index
  this.stack = [];
  // 存放key和value
  this.secretKey = {};
};

/**
  * @param {number} key
  * @return {number}
  */
LRUCache.prototype.get = function (key) {
  if (key in this.secretKey) {
    // 更新stack
    this.stack.splice(this.stack.indexOf(key), 1);
    this.stack.unshift(key);
    return this.secretKey[key];
  }
  else return -1;
};

/**
  * @param {number} key
  * @param {number} value
  * @return {void}
  */
LRUCache.prototype.put = function (key, value) {
  // key存在,仅修改值
  if (key in this.secretKey) {
    this.secretKey[key] = value;
    // 更新stack
    this.stack.splice(this.stack.indexOf(key), 1);
    this.stack.unshift(key);
  }
  // key不存在且栈未满
  else if (this.stack.length < this.capacity) {
    this.secretKey[key] = value;
    this.stack.unshift(key);
  }
  // key不存在且栈满
  else {
    // 删除key
    delete this.secretKey[this.stack[this.capacity - 1]]
    this.secretKey[key] = value;
    this.stack.pop();
    this.stack.unshift(key);
  }
};

/**
  * Your LRUCache object will be instantiated and called as such:
  * var obj = new LRUCache(capacity)
  * var param_1 = obj.get(key)
  * obj.put(key,value)
  */
let cache = new LRUCache(2);
cache.put(1, 1);
cache.put(2, 2);
console.log("cache.get(1)", cache.get(1))// 返回  1
cache.put(3, 3);// 该操作会使得密钥 2 作废
console.log(cache.stack);
console.log("cache.get(2)", cache.get(2))// 返回 -1 (未找到)
cache.put(4, 4);// 该操作会使得密钥 1 作废
console.log("cache.get(1)", cache.get(1))// 返回 -1 (未找到)
console.log("cache.get(3)", cache.get(3))// 返回  3
console.log("cache.get(4)", cache.get(4))// 返回  4

进阶版

利用ES6的Map对象,时间复杂度应该是O(1)

一个Map对象在迭代时会根据对象中元素的插入顺序来进行

//  一个Map对象在迭代时会根据对象中元素的插入顺序来进行
// 新添加的元素会被插入到map的末尾,整个栈倒序查看
class LRUCache {
  constructor(capacity) {
    this.secretKey = new Map();
    this.capacity = capacity;
  }
  get(key) {
    if (this.secretKey.has(key)) {
      let tempValue = this.secretKey.get(key);
      this.secretKey.delete(key);
      this.secretKey.set(key, tempValue);
      return tempValue;
    }
    else return -1;
  }
  put(key, value) {
    // key存在,仅修改值
    if (this.secretKey.has(key)) {
      this.secretKey.delete(key);
      this.secretKey.set(key, value);
    }
    // key不存在,cache未满
    else if(this.secretKey.size<this.capacity){
      this.secretKey.set(key, value);
    }
    // 添加新key,删除旧key
    else{
      this.secretKey.set(key,value);
      // 删除map的第一个元素,即为最长未使用的
      this.secretKey.delete(this.secretKey.keys().next().value);
    }
  }
}
let cache = new LRUCache(2);
cache.put(1, 1);
cache.put(2, 2);
console.log("cache.get(1)", cache.get(1))// 返回  1
cache.put(3, 3);// 该操作会使得密钥 2 作废
console.log("cache.get(2)", cache.get(2))// 返回 -1 (未找到)
cache.put(4, 4);// 该操作会使得密钥 1 作废
console.log("cache.get(1)", cache.get(1))// 返回 -1 (未找到)
console.log("cache.get(3)", cache.get(3))// 返回  3
console.log("cache.get(4)", cache.get(4))// 返回  4

做题心得

笔者的朋友在面试蚂蚁金服的时候遇到了类似的题目,所以考的概率应该蛮大的

get方法访问数据的时候,也算作使用数据,所以也应该刷新访问时间

原文地址:https://www.cnblogs.com/zhoujiayingvana/p/12683421.html

时间: 2024-11-09 02:48:59

JavaScript算法题实现-146-LRU缓存机制——腾讯面试题库的相关文章

[LeetCode]146.LRU缓存机制

设计和实现一个 LRU(最近最少使用)缓存 数据结构,使它应该支持以下操作: get 和 put . get(key) - 如果密钥存在于缓存中,则获取密钥的值(总是正数),否则返回 -1.put(key, value) - 如果密钥不存在,请设置或插入值.当缓存达到其容量时,它应该在插入新项目之前使最近最少使用的项目作废. 后续: 你是否可以在 O(1) 时间复杂度中进行两种操作?注:这道题也是2018今日头条春招面试题. 案例: LRUCache cache = new LRUCache(

JavaScript算法题之–随机数的生成

JavaScript算法题之–随机数的生成 需求描述:从一组有序的数据中生成一组随机并且不重复的数,类似于简单的抽奖程序的实现. 先来生成一个有序的数组: 1 var arr = [], 2     length = 100, 3     i = 0; 4   5 for( ; i < length; i++ ){ 6     arr.push( i ); 7 } 从一个长度为 100 的有序数组中随机拿出 10 个随机的数,并且不能有重复. 方法1:随机抽取法 01 var gRandomAr

FCC上的javascript算法题之中级篇

FCC中的javascript中级算法题解答 中级算法的题目中用到了很多js的知识点,比如迭代,闭包,以及对json数据的使用等等,现在将自己中级算法的解答思路整理出来供大家参考讨论.欢迎大家提出新的思路,写出更简单的解法. 1.给一个包含两个数字的数组.返回这两个数字和它们之间所有数字的和. 说明:最小的数字并非总在最前面 如:sumAll([4, 1]) 应该返回 10. sumAll([5, 10]) 应该返回 45. function sumAll(arr) { var max=Math

leecode第一百四十六题(LRU缓存机制)

class LRUCache { private: unordered_map<int, list<pair<int,int>>::iterator> _m; // 新节点或刚访问的节点插入表头,因为表头指针可以通过 begin 很方便的获取到. list<pair<int,int>> _list; int _cap; public: LRUCache(int capacity) : _cap(capacity) {} // O(1) // ha

LRU 缓存机制及 3 种简单实现

之前好几次接触到 LRU(Least Recently Used)算法,今天来总结下,并用 Java 和 Python 给出相应的实现. LRU是一种缓存替换算法,根据字面意思,就是将最近最少使用的页面或者元素进行替换,将最近最多使用的页面或者元素保持在缓存里.有关缓存的知识后面再仔细研究下.由于缓存的容量大小有限,这才有了LRU之类的缓存算法.还有一些其他的缓存算法,可以参考这个页面. 根据下面的图示进行LRU算法的理解. 其中 put 操作用于将最近使用的元素放置在缓存中,get 操作用于获

JavaScript算法题(二) &amp;&amp; 数组filter使用

1.Let's implement the reject() function... 例: var odds = reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); => [1, 3, 5] soluction: function reject(array, iterator) { return array.filter(function(x){return !iterator(x)}) } 2.The numbe

JavaScript算法题(一) &amp;&amp; 数组reduce使用

可参考Array.reduce用法 1. 请编写getMissingElement函数,返回给定数组中缺少的元素(数组里的元素为0~9,只会缺失一个). Example: getMissingElement( [0, 5, 1, 3, 2, 9, 7, 6, 4] ) // returns 8 getMissingElement( [9, 2, 4, 5, 7, 0, 8, 6, 1] ) // returns 3 soluction: function getMissingElement(su

LeetCode算法题-Maximum Average Subarray I(Java实现)

这是悦乐书的第278次更新,第294篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第146题(顺位题号是643).给定由n个整数组成的数组,找到具有最大平均值的长度为k的连续子数组,并输出最大平均值.例如: 输入:[1,12,-5,-6,50,3],k = 4 输出:12.75 说明:最大平均值为(12-5-6 + 50)/ 4 = 51/4 = 12.75 注意: 1 <= k <= n <= 30,000. 给定数组的元素将在[-10,000,10,00

LRU缓存算法

引子: 我们平时总会有一个电话本记录所有朋友的电话,但是,如果有朋友经常联系,那些朋友的电话号码不用翻电话本我们也能记住,但是,如果长时间没有联系了,要再次联系那位朋友的时候,我们又不得不求助电话本,但是,通过电话本查找还是很费时间的.但是,我们大脑能够记住的东西是一定的,我们只能记住自己最熟悉的,而长时间不熟悉的自然就忘记了. 其实,计算机也用到了同样的一个概念,我们用缓存来存放以前读取的数据,而不是直接丢掉,这样,再次读取的时候,可以直接在缓存里面取,而不用再重新查找一遍,这样系统的反应能力