题解 | #设计LRU缓存结构#

设计LRU缓存结构

http://www.nowcoder.com/practice/5dfded165916435d9defb053c63f1e84

这道题本质还是要手写LinkedHashMap。
运用Map是因为get 和set都是O(1),运用双向链表是因为插入和删除都是O(1)
同时还需要维护两个指针,一个指向最近一次掉用的节点,一个指向最久未调用的节点

    维护最近一次掉用节点,是为了在有新的get/set执行时,能迅速找到要查入的位置
    维持最久未调用,则是为了当超出节点数量时删除

/**
 * @param {number} capacity
 */

function ListNode (val){
    this.val = val;
    this.key = null;
    this.next = null;
    this.pre = null;
    
}

var Solution = function(capacity) {
    // write code here
    this.map = new Map();
    this.max = capacity;
    this.latestUsedPtr = null; //最近调用
    this.oldestUnusedPtr = null; //最久未调用
};

/** 
 * @param {number} key
 * @return {number}
 */
Solution.prototype.get = function(key) {
    // write code here
    
    if(this.map.has(key)){
        let valueNode = this.map.get(key);

        // 如果当前被get的节点不是最近一次调用过的,则将其提到第一个。
        if(valueNode.pre){
            // 如果当前节点是最久未调用,将最久未调用设为前一个
            if(!valueNode.next && valueNode.pre){
                this.oldestUnusedPtr = valueNode.pre;
            }
            //将该节点的前后节点连接起来,以维持链表结构
            valueNode.pre.next = valueNode.next;
            if(valueNode.next)
                valueNode.next.pre = valueNode.pre;
            
            //将该节点插入链表头
            valueNode.next = this.latestUsedPtr;
            this.latestUsedPtr.pre = valueNode;
            valueNode.pre = null;
            this.latestUsedPtr = valueNode;
            
        }
        return valueNode.val;
       
    }
    else{
        return -1;
    }
    
};

/** 
 * @param {number} key 
 * @param {number} value
 * @return {void}
 */
Solution.prototype.set = function(key, value) {
    // write code here
    
    let nodeToInsert = new ListNode(value);
    nodeToInsert.key = key;

    // 超出限额,拿掉最久未调用节点
    if(this.map.size === this.max && !this.map.has(key)){
       
        let preNode = this.oldestUnusedPtr.pre;
        preNode.next = null;
        this.map.delete(this.oldestUnusedPtr.key);
        this.oldestUnusedPtr = preNode;
    }
    // 已经存在该key
    if(this.map.has(key)){
        let curNode = this.map.get(key);
        //将旧节点从链表中移除
        if(curNode.pre){
            curNode.pre.next = curNode.next;
        }
        //将旧节点从表中移除
        this.map.delete(key);
    }
    
    
    // 将其添加到第一个,为最近掉用节点
    this.map.set(key,nodeToInsert);
    nodeToInsert.pre = null;
    nodeToInsert.next = this.latestUsedPtr;
    if(this.latestUsedPtr)
        this.latestUsedPtr.pre = nodeToInsert;
    
    if(nodeToInsert.next)
        nodeToInsert.next.pre = nodeToInsert;
    this.latestUsedPtr = nodeToInsert;
    // 如果只剩一个节点。
    if(!this.oldestUnusedPtr) 
        this.oldestUnusedPtr = nodeToInsert;

    return 
};

module.exports = {
    Solution : Solution
};

/**
 * Your Solution object will be instantiated and called as such:
 * var solution = new Solution(capacity)
 * var output = solution.get(key)
 * solution.set(key,value)
 */



全部评论

相关推荐

10-21 23:48
蚌埠坦克学院
csgq:可能没hc了 昨天一面完秒挂
点赞 评论 收藏
分享
评论
4
收藏
分享
正在热议
# 25届秋招总结 #
440109次浏览 4488人参与
# 春招别灰心,我们一人来一句鼓励 #
41427次浏览 524人参与
# 北方华创开奖 #
107270次浏览 599人参与
# 地方国企笔面经互助 #
7916次浏览 18人参与
# 虾皮求职进展汇总 #
113709次浏览 881人参与
# 实习,投递多份简历没人回复怎么办 #
2453743次浏览 34846人参与
# 阿里云管培生offer #
119719次浏览 2219人参与
# 实习必须要去大厂吗? #
55563次浏览 960人参与
# 同bg的你秋招战况如何? #
75265次浏览 549人参与
# 提前批简历挂麻了怎么办 #
149784次浏览 1977人参与
# 投递实习岗位前的准备 #
1195641次浏览 18546人参与
# 你投递的公司有几家约面了? #
33170次浏览 188人参与
# 双非本科求职如何逆袭 #
661802次浏览 7394人参与
# 机械人春招想让哪家公司来捞你? #
157587次浏览 2267人参与
# 如果公司给你放一天假,你会怎么度过? #
4717次浏览 54人参与
# 如果你有一天可以担任公司的CEO,你会做哪三件事? #
11266次浏览 263人参与
# 发工资后,你做的第一件事是什么 #
12368次浏览 61人参与
# 工作中,努力重要还是选择重要? #
35546次浏览 384人参与
# 参加完秋招的机械人,还参加春招吗? #
20072次浏览 240人参与
# 实习想申请秋招offer,能不能argue薪资 #
39211次浏览 314人参与
# 我的上岸简历长这样 #
451881次浏览 8088人参与
# 非技术岗是怎么找实习的 #
155832次浏览 2120人参与
牛客网
牛客企业服务