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.

为了寻求速度,基本是hash table,O(1)。怎么维护LRU呢?可以用一个链表,访问过的元素放到末端。链表的插入删除都是O(1)。

class LRUCache{
public:
    LRUCache(int capacity) {
        this->capacity = capacity;
        size = 0;
    }
    
    int get(int key) {
        int value = -1;
        auto iter = cache_map.find(key);
        if (iter != cache_map.end()) {
            value = iter->second->second;
            cache_list.erase(iter->second);
            cache_map[key] = cache_list.insert(cache_list.end(), make_pair(key, value));
        }
        
        return value;
    }
    
    void set(int key, int value) {
        auto iter = cache_map.find(key);
        if (iter != cache_map.end()) {
            cache_list.erase(iter->second);
        }
        else {
            if (size < capacity) {
                ++size;
            }
            else {
                auto front = cache_list.front();
                cache_map.erase(front.first);
                cache_list.pop_front();
            }
        }
        cache_map[key] = cache_list.insert(cache_list.end(), make_pair(key, value));
    }
    
private:
    int capacity;
    int size;
    list<pair<int, int> > cache_list; // key-value pair
    typedef list<pair<int, int> >::iterator pnode;
    unordered_map<int, pnode> cache_map; // key - iterator to list
};

==========================第二次=======================

上面用了list+map来实现,如果要求只用一个Map来实现呢?先后关系是必须要维护的,所以只能在map里面自己维护先后顺序了。这种方式容易出错啊,指针操作,边界条件,一个元素的情况,总之折腾很久。

struct LRUListNode {
    int key;
    int val;
    LRUListNode *next;
    LRUListNode *prev;
    
    LRUListNode(int key, int val) {
        this->key = key;
        this->val = val;
        next = NULL;
        prev = NULL;
    }
};
    
class LRUCache{
public:
    LRUCache(int capacity) {
        m_capacity = capacity;
        if (m_capacity == 0) {
            m_capacity = 10;
        }
        m_size = 0;
        m_oldest = NULL;
        m_latest = NULL;
    }
    
    int get(int key) {
        int val = -1;
        auto iter = m_lruMap.find(key);
        if (iter != m_lruMap.end()) {
            LRUListNode *tmp = iter->second;
            val = tmp->val;
            
            // If it is the last one, no need update.
            if (tmp != m_latest) {
				if (tmp->prev != NULL) {
					tmp->prev->next = tmp->next;
				}
				tmp->next->prev = tmp->prev;
            
				if (m_oldest == tmp) {
					m_oldest = tmp->next;
					m_oldest->prev = NULL;
				}
				joinNode(m_latest, tmp);
				tmp->next = NULL;
				m_latest = tmp;
			}
        }
        
        return val;
    }
    
    void set(int key, int value) {
        if (get(key) != -1) {
            m_latest->val = value;
        }
        else {
            if (m_size < m_capacity) {
                LRUListNode *inserted = new LRUListNode(key, value);
                m_lruMap[key] = inserted;
                ++m_size;
                
                if (m_latest != NULL) {
                    joinNode(m_latest, inserted);
                }
                m_latest = inserted;
                if (m_oldest == NULL) {
                    m_oldest = inserted;
                }
            }
            else {
                LRUListNode *deleting = m_oldest;
                m_lruMap.erase(deleting->key);
                deleting->key = key;
                deleting->val = value;
                m_lruMap[key] = deleting;
                
                // If capacity is only 1, no need update.
                if (m_oldest != m_latest) {
                    m_oldest = m_oldest->next;
                    m_oldest->prev = NULL;
                    joinNode(m_latest, deleting);
                    deleting->next = NULL;
                    m_latest = deleting;
                }
            }
        }
    }
    
private:

    void joinNode(LRUListNode *n1, LRUListNode *n2) {
        n1->next = n2;
        n2->prev = n1;
    }
    
    int m_capacity;
    int m_size;
    
    LRUListNode *m_oldest;
    LRUListNode *m_latest;
    unordered_map<int, LRUListNode*> m_lruMap;
};


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值