zoukankan      html  css  js  c++  java
  • [LeetCode] LRU Cache

    Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set.

    get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1. set(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

    分析: 关键是对Least Recently Used (LRU) cache的理解,如果用链表,遇到一个结点,将链表中出现的这个结点全删除,然后在链表末尾加上这个结点。

    链表末尾表示最近访问的结点,链表头表示最久前访问的结点,如果cache满了,要删除结点,就删除链表头结点。但这样做每次都要遍历链表,所以速度特别慢,

    总是提示Time Limited Exceeded!

    #include<iostream>
    #include<map>
    
    using namespace std;
    
    struct Lnode
    {
      int key0;
      int value0;
      Lnode *next;
      Lnode *pre;
      Lnode(int key,int value):key0(key),value0(value),next(NULL),pre(NULL){}
      Lnode():next(NULL),pre(NULL){}
    };
    class LRUCache{
    public:
        int capacity;
        int    capacityNow;
        Lnode *head;
        Lnode *h ;
        map<int,int> ma,mNum;//ma记录key和value,mNum记录key和出现的次数
        
        
        LRUCache(int capacity)
        {
          this->capacity = capacity;
          this->capacityNow = 0;
          head = new Lnode;
          h = head;
        }
       
        void set(int key,int value)
        {
            int num;
            del(head,key);//
            if(ma.count(key)>0)//修改
            {
               mNum.clear();
               mNum[key]++;
               ma[key]=value;
               mNum[key]++;
               return;
            }
            
            if(this->capacityNow >= this->capacity)//添加
            {
                
               Lnode *pTobedeleted = head->next;
               while(mNum.count(pTobedeleted->key0)!=0 && this->capacityNow != 1)
               {
                 
                  pTobedeleted = pTobedeleted->next;
               }
               
               ma.erase(pTobedeleted->key0);
               Lnode *p0 = pTobedeleted->next;
               if(p0)
                 p0->pre = head;
               head->next = p0;
               
               ma[key] = value;
               
               Lnode *pnew = new Lnode(key,value);
               h->next = pnew;
               pnew->pre = h;
               h = pnew;
               mNum.clear();
               mNum[key]++;
            }
            else
            {
                mNum.clear();
                mNum[key]++;
                ma[key] = value;
                this->capacityNow++;
                Lnode *p = new Lnode(key,value);
                h->next = p;
                p->pre = h;
                h = p;
                
            }
            
    
        }
    
        int get(int key)
        {
            
    
            if(ma.count(key)>0)
            {
                
                del(head,key);//
                mNum.clear();
                mNum[key]++;
                
                Lnode *pnew = new Lnode(key,ma[key]);
                h->next = pnew;
                pnew->pre = h;
                h = pnew;
               
    
                return ma[key];
            }
            else
               return -1;
        }
    private:
        void del(Lnode *head,int key)
        {
           Lnode *p=head->next,*p1;
           Lnode *h1 = head;
           while(p)
           {
               
               p1 = p->next;
             if(p->key0 == key)
             {
               h1->next = p1;
               if(p1)
                 p1->pre = h1;
             }
             h1 = p;
             p = h1->next;
           }
           if(h1->key0 == key)
               this->h = h1->pre;
           else
               this->h = h1;
        
          
        }
    };

    这道题如果稍微有一点需要遍历的,就会超时,以下是Accept的方法:

    #include<iostream>
    #include<map>
    
    using namespace std;
    
    struct Lnode
    {
      int key0;
      int value0;
      Lnode *next;
      Lnode *pre;
      Lnode(int key,int value):key0(key),value0(value),next(NULL),pre(NULL){}
      Lnode():next(NULL),pre(NULL){}
    };
    class LRUCache{
    public:
        int capacity;
        int    capacityNow;
        Lnode *head;
        Lnode *h ;
        map<int,int> ma,mNum;//ma记录key和value,mNum记录key和出现的次数
        
        
        LRUCache(int capacity)
        {
          this->capacity = capacity;
          this->capacityNow = 0;
          head = new Lnode;
          h = head;
        }
       
        void set(int key,int value)
        {
            
            if(ma.count(key)>0)//修改
            {
               
               ma[key]=value;
    
               Lnode *pnew = new Lnode(key,value);
               h->next = pnew;
               pnew->pre = h;
               h = pnew;
               
               mNum[key]++;
               return;
            }
            
            if(this->capacityNow >= this->capacity)//添加
            {
                   
               Lnode *pTobedeleted = head->next;
               
               int num = mNum[pTobedeleted->key0];
               while(num !=1 || ma.count(pTobedeleted->key0)==0)//在链表中找到一个存在于ma的,且最久前没用的结点
               {
                  mNum[pTobedeleted->key0]--;
                  pTobedeleted = pTobedeleted->next;
                  num = mNum[pTobedeleted->key0];
               }
               mNum[pTobedeleted->key0] = 0;
               head->next = pTobedeleted->next;
               ma.erase(pTobedeleted->key0);
               ma[key] = value;
               
               Lnode *pnew = new Lnode(key,value);
               h->next = pnew;
               pnew->pre = h;
               h = pnew;
               
               mNum[key]++;
            }
            else
            {
                
                mNum[key]++;
                ma[key] = value;
                this->capacityNow++;
                Lnode *p = new Lnode(key,value);
                h->next = p;
                p->pre = h;
                h = p;
                
            }
            
    
        }
    
        int get(int key)
        {
            
    
            if(ma.count(key)>0)
            {
                mNum[key]++;
                
                Lnode *pnew = new Lnode(key,ma[key]);
                h->next = pnew;
                pnew->pre = h;
                h = pnew;
               
    
                return ma[key];
            }
            else
               return -1;
        }
        
    };

    将访问到的结点不断的添加到链表中,同时cache满需要删除结点时,将链表的头结点往后移。用一个结点出现的次数mNum判断一个链表的结点是否是需要删除的结点。

  • 相关阅读:
    Django项目总结:项目主页
    变量、常量和作用域
    mysql数据库连接
    多线程下的单例模式
    JVM笔记--类文件结构
    Java初始化与清理
    多线程设计模式-单线程执行模式
    Java语言实现冒泡排序算法
    继承父类并实现多个接口_hehe.base.10.3
    Servlet | Request 对象获取请求参数的通用方式
  • 原文地址:https://www.cnblogs.com/Xylophone/p/3843588.html
Copyright © 2011-2022 走看看