Skip to content

LRU 缓存 #180

@TieMuZhen

Description

@TieMuZhen

image
image

法一:Map+双指针

该法讲解视频

function Node(key, value) {
    this.key = key;
    this.value = value;
    this.pre = null;
    this.next = null;
}

function DoubleLinkedList() {
    this.head = new Node(0, 0);
    this.tail = new Node(0, 0);
    this.head.next = this.tail;
    this.tail.pre = this.head;
}
DoubleLinkedList.prototype.addNodeToFirst = function (node) {
    node.pre = this.head;
    node.next = this.head.next;

    this.head.next.pre = node;
    this.head.next = node;
}

DoubleLinkedList.prototype.deleteNode = function (node) {
    node.pre.next = node.next;
    node.next.pre = node.pre;
    return node.key;
}

DoubleLinkedList.prototype.deleteLastNode = function () {
    if(this.head.next == this.tail) return -1;
    return this.deleteNode(this.tail.pre);
}

/**
 * @param {number} capacity
 */
var LRUCache = function(capacity) {
    this.map = new Map();
    this.cache = new DoubleLinkedList();
    this.capacity = capacity;
};

/** 
 * @param {number} key
 * @return {number}
 */
LRUCache.prototype.get = function(key) {
    if(!this.map.has(key)) return -1;
    // 更新缓存中的key
    const value = this.map.get(key).value;
    this.put(key, value);
    return value;
};

/** 
 * @param {number} key 
 * @param {number} value
 * @return {void}
 */
LRUCache.prototype.put = function(key, value) {
    const newNode = new Node(key, value);
    if(!this.map.has(key)){
        if(this.map.size == this.capacity){ // 如果存储的数据已到最大容量
            let oldKey = this.cache.deleteLastNode();
            this.map.delete(oldKey);
        }
        this.map.set(key, newNode);
        this.cache.addNodeToFirst(newNode);
    }else{
        // 更新list中对应节点为最新使用过的
        this.cache.deleteNode(this.map.get(key));
        this.cache.addNodeToFirst(newNode);
        // 更新map中对应节点为最新使用过的
        this.map.set(key, newNode);
    }
};

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

法二:巧用 Map 数据结构

首先明确一个性质,Map 这个 ES6 新增数据结构是 有序的,即不仅可以存储键值对(关键字-值),还可以通过 delete 和 set 的 API 对> 数据进行更新,最后 set 的数据默认在 Map 的末尾(最新)

因此利用好上面的性质,这题其实非常容易了,对于题目的 第二点 和 第三点 要求,在每次 get 和 put 已存在队列中的值,或新增值,直接 delete 删掉后,再 set 进行更新到 Map 最后即可(最新)

/**
 * @param {number} capacity
 */
 var LRUCache = function(capacity) {
    this.map = new Map();
    this.capacity = capacity;
};

/** 
 * @param {number} key
 * @return {number}
 */
LRUCache.prototype.get = function(key) {
    if(this.map.has(key)){
        let value = this.map.get(key);
        this.map.delete(key); // 删除后,再 set ,相当于更新到 map 最后一位
        this.map.set(key, value);
        return value
    } else {
        return -1
    }
};

/** 
 * @param {number} key 
 * @param {number} value
 * @return {void}
 */
LRUCache.prototype.put = function(key, value) {
    // 如果已有,那就要更新,即要先删了再进行后面的 set
    if(this.map.has(key)){
        this.map.delete(key);
        this.map.set(key, value);
    }else{
        // put 后判断是否超载
        if(this.map.size == this.capacity){
            this.map.delete(this.map.keys().next().value); // 删除Map第一个元素
        }
        this.map.set(key, value);
    }
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions