Implementation of JavaScript algorithm questions -146-LRU cache mechanism-Tencent interview question bank

Problem index (maximum 5): ⭐⭐⭐⭐

topic

Design and implement an LRU (least recently used) caching mechanism using the data structure you have. It should support the following: Obtain the data getand write data put.

Get data get(key)-If the key exists in the cache, get the value of the key (always a positive number), otherwise return -1.
Write data put(key, value)-If the key already exists, change its data value; if the key does not exist, insert the group "key / data value". When the cache capacity reaches the upper limit, it should delete the longest unused data value before writing new data to make room for the new data value.

Advanced:

Can you accomplish both operations within O (1) time complexity?

Example:

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 original question guide

answer

LRU cache mechanism

The abbreviation of Least Recently Used, that is the least recently used.

principle

Select the most recently unused page to be eliminated. The algorithm gives each page an access field to record the time t that a page has experienced since it was last visited. When a page needs to be eliminated, the current page with the largest t value is selected, which is the least recently used The page is eliminated.

Assuming that the memory can only accommodate 3 page sizes, the pages are accessed in the order of 7 0 1 2 0 3 0 4. Suppose the memory describes the access time according to the stack. On the top, it is the most recently accessed, and on the bottom, it is the farthest time. The LRU works this way.

img

Ideas

This question does not involve complex algorithms, just use the stack. If it is to be completed in O (1) time, consider the Maptarget of ES6 .

JavaScript implementation

regular version

Time complexity is not necessarily 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

Advanced Edition

Using ES6 Mapobjects, the time complexity should be O (1)
A Map object will be performed according to the insertion order of the elements in the object during iteration

//  一个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

Experience

My friend encountered a similar problem during the interview with Ant Financial, so the probability of the test should be quite large. When
getaccessing the data, it is also counted as usage data, so the access time should also be refreshed.

Guess you like

Origin www.cnblogs.com/zhoujiayingvana/p/12683421.html