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

设计LRU缓存结构

http://www.nowcoder.com/practice/e3769a5f49894d49b871c09cadd13a61

使用的结构是hash表+双链表,重点是掌握hash表和双链表的构造以及this指针的运用。

struct DListNode{
    int key,val;//hash表
    DListNode *pre;//双链表
    DListNode *next;
    DListNode(int k,int v):key(k),val(v),pre(NULL),next(NULL){};
};

class Solution {
private:
    int size=0;
    DListNode *head;
    DListNode *tail;
    unordered_map<int,DListNode*> mp;

public:
    /**
     * lru design
     * @param operators int整型vector<vector<>> the ops
     * @param k int整型 the k
     * @return int整型vector
     */
    vector<int> LRU(vector<vector<int> >& operators, int k) {
        // write code here
        //要学会this指针的运用!!
        if(k<1)
            return {};//最大容量小于1则返回空数组
        this->size=k;//链表最大容量
        this->head=new DListNode(0,0);
        this->tail=new DListNode(0,0);
        this->head->next=this->tail;
        this->tail->pre=this->head;
        if(operators.size()==0)
            return {};
        vector<int> res;
        for(vector<int> op:operators)
        {//op表示operators数组集的每一个数组
            if(op[0]==1)
                set(op[1], op[2]);//插入新结点
            else if(op[0]==2)
            {//返回其value
                int value=get(op[1]);
                res.push_back(value);
            }
        }
        return res;
    }

public:
    void set(int key,int val)
    {//将记录(key,value)插入链表
        DListNode* node=new DListNode(key,val);//要插入的新结点
        if(mp.count(key))
        {//原mp中已存在key,只需改变val值,并移到head后
            mp[key]->val=val;
            moveTohead(mp[key]);
        }
        else
        {//原mp中不存在,则先判断当前链表大小,若小于1则删除最后一个结点,若大于1则当前大小减1,再在head后插入新节点
            mp[key]=node;
            if(this->size<1)
                remove();
            else
                this->size--;
            addFront(node);
        }
    }

public:
    int get(int key)
    {//提取key值对应value,若不存在则返回-1,若存在则返回value并将所在结点提前至head后
        if(!mp.count(key))
            return -1;
        int val=mp[key]->val;//注意mp[key]表示该结点
        moveTohead(mp[key]);
        return val;
    }

public:
    void addFront(DListNode* node)
    {//在链表头部添加结点node
        node->pre=this->head;
        node->next=this->head->next;//确定node的前驱后驱分别指向
        this->head->next->pre=node;
        this->head->next=node;//确定node的两个被指向
    }

public:
    void remove()
    {//删除链表最后一个结点
        mp.erase(this->tail->pre->key);//清除最后一个结点的key值
        this->tail->pre->pre->next=this->tail;//清除最后一个结点的前后连接关系
        this->tail->pre=this->tail->pre->pre;//并建立tail与倒数第二个结点的关系
    }

public:
    void moveTohead(DListNode* node)
    {//将结点移到头部
        if(node->pre==this->head) 
            return;//node在head后面即退出
        node->pre->next=node->next;//node前驱结点与node后驱(即tail)建立连接
        node->next->pre=node->pre;
        addFront(node);//在head后插入node,作为第一个结点
    }

};
全部评论

相关推荐

搜索部&nbsp;首先说下timeline8.18,投递8.19,约一面8.21,晚上一面call约二面8.22,上午二面下午oc周末等待(8.23,8.24)8.25,offer一年前,我还是懵懵懂懂,高考完的暑假,只会提前学学高数,未来的画像是什么?我或许无法预测。开学后,自学Python,接单,无数个客户的ddl,偷偷摸摸一个人找自习的地方,这一步步竟然为后来的我,搭建工程能力的基础。大一上,我也要感谢我的第一位老板,让我接触到了实习,师兄带着我一步步入门,看他们写的飞书文档。大一下,导师带我参与企业项目,这让我渐渐发现,应该去实践,增长见识,而非局限当下,盯着自己的小新pro。不久后,第一波投递开始,结果当然是约面极少。盯着简历上的文字和ssob,我开始思考,确实很多可以去提升。带着些许不甘心,继续沉淀,慢慢的约面也越来越多,有的时候两天7场,准备完就接着下一个日程。这一次,也许是刚好到位吧,比较match,面试答的流利,关关难关关过,成为度孝子展望未来,依然是重重挑战,果然只有收到offer的那一刻是开心的。愿在百度星海拆解的每一段代码,都能成为丈量宇宙的诗行;此志终赴星河,而今迈步重铸天阶。屏幕前的你们,在无数个向星海奔赴的日夜,一定一定,会在未来化作群星回响的征程——请永远相信此刻埋首耕耘的自己!!!
一天三顿半:???百度提前批发 offer了?不是统一和正式批排序完再发吗我靠
百度求职进展汇总
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务