LeetCode (26) 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.

题目要求我们实现一个缓存数据结构。要求的主要操作为获取(get)和插入(set)。需要注意的是,当缓存满了的时候,在set时需要删除最长时间没有使用的元素,并插入新元素。这就要求我们在数据结构中设计一个方法要么记录每个元素的被使用顺序,要么根据元素的被使用顺序保存元素。需要注意的是,在get元素的时候,如果元素存在于缓存中,则该元素的被使用顺序要被提前。

可以通过使用双向链表表示缓存中数据。链表的头部表示最近被使用的元素,链表的尾部表示最长时间没被使用的元素。当获取/插入元素时,将元素放置在链表的头部。需要注意的是,若插入的元素的key已经存在于缓存中,则要删除原来的数据(key, value)结点。

我们知道对链表进行随机访问的时间复杂度为O(n),那么上面的数据结构每次获得和插入元素的时间复杂度都为O(n)。为了减小时间复杂度,我们可以使用一个map结构,通过key保存结点位置,时间复杂度为O(logn)。如果要求更高的时间效率还可以使用unordered_map取代map保存结点位置。

map结构如下:

map<int, node*> cache;

根据上述思路得到的完整代码如下:

struct node
{
    int key;
    int value;
    node* pre;
    node* next;
    node(int k, int v) :key(k), value(v), pre(NULL), next(NULL) {};
};

class LRUCache{
private:
    int m_capacity;
    int m_size;
    node* m_head;
    node* m_tail;
    map<int, node*> m_cache;
public:

    LRUCache(int capacity) {
        m_capacity = capacity;
        m_size = 0;
        m_head = new node(0, 0);
        m_tail = new node(0, 0);
        m_head->next = m_tail;
        m_tail->pre = m_head;
        m_cache.clear();
    }

    ~LRUCache() {
        delete m_head;
        delete m_tail;

        map<int, node*>::iterator it;
        for (it = m_cache.begin(); it != m_cache.end(); ++it)
        {
            delete(it->second);
        }
        m_cache.clear();
    }

    void putTohead(node* cur)
    {
        cur->next = m_head->next;
        cur->next->pre = cur;
        m_head->next = cur;
        cur->pre = m_head;      
    }

    int get(int key) {
        map<int, node*>::iterator it = m_cache.find(key);
        if (it != m_cache.end())
        {
            node* cur = it->second;
            cur->pre->next = cur->next;
            cur->next->pre = cur->pre;
            putTohead(cur);
            return cur->value;
        }
        else
            return -1;
    }

    void set(int key, int value) {      
        map<int, node*>::iterator it = m_cache.find(key);
        if (it != m_cache.end())
        {
            node* cur = it->second;
            cur->value = value;
            cur->pre->next = cur->next;
            cur->next->pre = cur->pre;
            putTohead(it->second);
        }
        else 
        {
            node* new_node = new node(key, value);
            putTohead(new_node);
            m_cache[key] = new_node;
            if (m_size < m_capacity)
                m_size++;
            else
            {
                node* del = m_tail->pre;
                del->pre->next = m_tail;
                m_tail->pre = del->pre;
                it = m_cache.find(del->key);
                m_cache.erase(it);
                delete del;
            }
        }
    }
};

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