zoukankan      html  css  js  c++  java
  • 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.

    思路:

    本题的一大特色是使用了双向链表。并且含有两个函数,spilt 和 insert 函数,插入就是把一个节点插入头结点之后的操作函数,而分开就是把当前节点从原有链表中分离出来。

    需要说明的是:head 和 tail 节点并不算任何节点。

    首先是get 函数:

    首先用哈希表查找是否存在,不存在直接返回-1。如果存在,则由于访问了当前数据,先是分离当前节点,再将其插入到最前面。最后返回其值。

    其次是set 函数:

    先是使用get 函数判断是否存在,注意:如果存在,get 函数已经进行分离和插入操作了。
    如果不存在,还需要判断是否超过大小。这里使用hash表的大小判断。没有越界,直接赋值新节点,越界了,先是分离,再插入新节点。

    代码:

    class LRUCache{
    private:
        struct Node{
            int key;
            int value;
            Node *prev,*next;
            Node(int k,int v):key(k),value(v),prev(NULL),next(NULL){}
        };
        
        unordered_map<int , Node*>mapper;
        Node *head,*tail;
        int capacity;
        
        void insert(Node *target){
            target->next=head->next;
            head->next->prev=target;
            head->next=target;
            target->prev=head;
        }
        
        void split(Node *target){
            target->prev->next=target->next;
            target->next->prev=target->prev;
            //insert(target);
        }
        
    public:
        LRUCache(int capacity) {
            this->capacity=capacity;
            head=new Node(0,0);
            tail=new Node(0,0);
            head->next=tail;//设立开头结尾指针,方便操作
            tail->prev=head;
        }
        
        int get(int key) {
            if(mapper.find(key)==mapper.end()){
                return -1;
            }
            Node *target=mapper[key];
            
            if(target!=head->next){//如果不是第一个,那么根据最小使用原则,使用了一次target,把他挪到
                                 //最前面
                split(target);
                insert(target);
            }
            
            return target->value;
        }
    
        void set(int key, int value) {
            if(get(key)!=-1){//  数值已经存在
                head->next->value=value;//get 这个函数里面已经有分离 插入 这些操作了.
                return;
                
            }
            //下面判断不存在,但是要考虑是否越界
            
            Node *tmp=NULL;
            if(mapper.size()==capacity){
                tmp=tail->prev;
                split(tmp);
                mapper.erase(tmp->key);
                tmp->value=value;
                tmp->key=key;
            }/*
                tmp->value=value;
                tmp->key=key;*/  // 不能这么写,因为上面定义的tmp是一个单链表指针,这样赋值是双链表指针
            tmp=new Node(key,value);
            mapper[key]=tmp;
            insert(tmp);
        }
    };


  • 相关阅读:
    在Oracle中计算两个日期间隔的天数、月数和年数
    洛谷P1182 数列分段 Section II(二分+贪心)
    BZOJ1734 [Usaco2005 feb]Aggressive cows 愤怒的牛(二分答案+贪心)
    分治算法
    洛谷P1031 [NOIP2002]均分纸牌
    洛谷P1803 凌乱的yyy / 线段覆盖
    洛谷P1094 [NOIP2007]纪念品分组
    洛谷P1223 排队接水
    洛谷P1208 [USACO1.3]混合牛奶 Mixing Milk
    洛谷P1181 数列分段Section1
  • 原文地址:https://www.cnblogs.com/jsrgfjz/p/8519849.html
Copyright © 2011-2022 走看看