Leetcode前端必会系列:LRU缓存

54 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第16天,点击查看活动详情

引言

算法的技能对于程序员是百益而无一害,作为程序员无论是前端还是后端算法技能对于我们都是十分十分的重要,我将陆续整理并讲解前端程序员必须掌握的经典算法。

题目描述

请你设计并实现一个满足  LRU (最近最少使用) 缓存 约束的数据结构。

实现 LRUCache 类:

  • LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
  • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。

 

示例:

输入
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出
[null, null, null, 1, null, -1, null, -1, 3, 4]

解释
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1);    // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2);    // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1);    // 返回 -1 (未找到)
lRUCache.get(3);    // 返回 3
lRUCache.get(4);    // 返回 4

提示:

  • 1 <= capacity <= 3000
  • 0 <= key <= 10000
  • 0 <= value <= 105
  • 最多调用 2 * 105 次 get 和 put

分析

根据题目的分析,我们如何设计一个简单的LRU缓存?根据LRU的特性我们可以使用js内置的map数据结构来模拟lru的操作过程。

  1. 初始化一个lru存储,并设计类构造最大的存储空间
  2. 设计添加的方法,每次判断如果当前元素存在,先删除元素,然后将元素添加到map里面。如果元素不存在,每次先判断是否存储空间最大了,如果最大了,先删除最开始的元素,然后添加元素。否则直接添加元素
  3. 获取元素,先判断元素是否存在,如果存在,先删除,然后添加。最后返回获取的元素。否则返回空

解答

   /**

 * @param {number} capacity

 */

var LRUCache = function(capacity) {

    this.size = capacity

    this.m = new Map()

};




/**

 * @param {number} key

 * @return {number}

 */

LRUCache.prototype.get = function(key) {

    //访问的需要重新添加

    if(this.m.has(key)) {

        let val = this.m.get(key)

        this.m.delete(key)

        this.m.set(key,val)

        return val

    }

    return -1

};




    /**

     * @param {number} key

     * @param {number} value

     * @return {void}

     */

    LRUCache.prototype.put = function(key, value) {

        //1.判断是否存在

        if(this.m.has(key)) {

            let val = this.m.get(key)

            this.m.delete(key)

            this.m.set(key,value)

        }else{

            //2.判断是否满

            if(this.m.size===this.size) {

                //3.删除最头的那个

                let front = this.m.keys().next().value

                this.m.delete(front)

                this.m.set(key,value)

            }else{

                this.m.set(key,value)

            }

        }

    };




    /**

     * 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)

     */

通过题目的分析,我们按照lru设计的规则完成设计,整体的设计还是比较容易的