leetcode || 146、LRU Cache

problem:

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.

Hide Tags
 Data Structure
题意:实现LRU算法,题意没有详细说明怎么度量最近最少使用,难点所在

thinking:

(1)这道题我自己借助unordered_map和list实现了一个版本,小数据测试通过,大数据测试时(连续set、get),由于频繁的操作map、list,超时了。

最高效的做法是将list嵌入到节点的结构体中。

        我的思路:构建一个包含key值和访问次数visited的结构体,每次访问结构体对象时,访问次数+1,在节点数未达到上限时,将新节点插入到list的头部。在达到上限时,

将访问次数最小的节点移到list的末尾,移除尾部节点,在list头部插入新的节点。使用unordered_map提高超找效率。

code:

class node{
public:
    int _key;
    int _visited;
    node(int key, int visited):_key(key),_visited(visited){}
};
class LRUCache{
private:
   unordered_map<int,list<node *>::iterator> map_record;
    list<node *> list_record;
    int size;
public:
    LRUCache(int capacity) {
        size=capacity;
    }

    int get(int key) {
        if(map_record.count(key)!=0)
        {
           unordered_map<int,list<node *>::iterator>::iterator it_a=map_record.find(key);
            list<node *>::iterator it_b=it_a->second;
            node *node_tmp=*it_b;
            node_tmp->_visited+=1;
            adjust();
            return key;
        }
        else
            return -1;
    }

    void set(int key, int value) {
        if(map_record.count(key)!=0)
        {
           unoredered_map<int,list<node *>::iterator>::iterator it_a=map_record.find(key);
            list<node *>::iterator it_b=it_a->second;
            node *node_tmp=*it_b;
            node_tmp->_key=value;
            node_tmp->_visited+=1;
        }
        else
        {
            if(list_record.size()<size)
            {
                node *tmp_node=new node(value,1);
                list_record.push_front(tmp_node);
                list<node *>::iterator it=find(list_record.begin(),list_record.end(),tmp_node);
                map_record.insert(make_pair(value,it));
            }
            else
            {
                adjust();
               node *tmp_node=new node(value,1);
               list_record.push_front(tmp_node);
               map_record.clear();
               for(list<node *>::iterator it=list_record.begin();it!=list_record.end();++it)
               {
                   node *tmp=*it;
                   map_record.insert(make_pair(tmp->_key,it));
                   }
            }
        }

    }
protected:
    void adjust()
    {
        if(list_record.empty())
            return;
        node *index=list_record.back();
        list<node *>::iterator min_it;
        int min_visited=index->_visited;
        for(list<node *>::iterator it=list_record.begin();it!=list_record.end();++it)
        {
            node *tmp_node = *it;
            if(tmp_node->_visited<min_visited)
                min_it=it;
        }
        list<node *>::iterator last=list_record.end();
        swap(min_it,--last);
        list_record.pop_back();
    }
};



一个高效且测试通过的版本:

struct CacheNode {
    int key;
    int value;
    CacheNode* next;
    CacheNode* prev;
    CacheNode(int _key, int _value) {
        key = _key;
        value = _value;
        next = nullptr;
        prev = nullptr;
    }
};
class LRUCache{
public:
    LRUCache(int capacity) {
        _capacity = capacity;
        head = new CacheNode(INT_MIN,-1);
        tail = head->next;
        len = 0;
    }
    
    int get(int key) {
        auto found = cache.find(key);
        if (found != cache.end()) {
            if (found -> second == tail) {
              tail = tail->prev;
            }
            insertToHead(found->second);
            if (tail == head) tail = head -> next;
            return found -> second -> value;
        }
        return -1;
    }
    
    void set(int key, int value) {
        auto found = cache.find(key);
        if (found != cache.end()) {
            found->second->value = value;
            if (found -> second == tail) {
              tail = tail->prev;
            }
            insertToHead(found->second);
            if (tail == head) tail = head->next;
            return ;
        }
        if (len == _capacity) {
            CacheNode* tmp = tail -> prev;
            cache.erase(tail->key);
            deleteNodeLink(tail);
            delete tail;
            tail = tmp;
            insertToHead(new CacheNode(key, value));
            return ;
        }
        insertToHead(new CacheNode(key, value));
        if (tail == nullptr) tail = head->next;
        len++;
    }
private:
   CacheNode* head;
   CacheNode* tail;
   int _capacity;
   int len;
   unordered_map<int, CacheNode*> cache;
   
   void deleteNodeLink(CacheNode* node) {
       CacheNode* prev = nullptr;
       CacheNode* next = nullptr;
       if (node -> prev) prev = node->prev;
       if (prev) {
           prev -> next = node -> next;
       }
       if(node->next) next = node -> next;
       if(next) {
           next -> prev = prev;
       }
   }
   
   void insertToHead(CacheNode* node) {
       deleteNodeLink(node);
       node->prev = head;
       node->next = head->next;
       if (head -> next) head->next->prev = node;
       head->next = node;
       cache[node->key] = node;
   }
};


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。