【leetcode】LRU Cache(hard)★

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时把最老的数据扔掉,把新的插入到最近的位置。

关键是,如何在O(1)的时间内get到所需的数据,如何在O(1)的时间内,找到最老的数据。

第一个问题可以用unordered_map轻松解决,但是,第二个问题我就不会了。我很low的用了遍历,果断超时了。看答案后发现,要用list的splice函数解决。

把所有的数据按照访问时间由近到远存放在一个list中,当再次访问里面的数据时,就把该数据移动到list的开始位置,满了后就移除list的最后一个元素。

上大神的答案:

class LRUCache {
private:
    // A list of (key, value) pairs
    list<pair<int, int>> items;
    // Map items to iterators (pointers) to list nodes
    unordered_map<int, list<pair<int, int>>::iterator> cache;
    // The capacity of the list
    int capacity;

public:
    LRUCache(int capacity) : capacity(capacity) {}

    int get(int key) {
        // If key is not found in hash map, return -1
        if (cache.find(key) == cache.end())
            return -1;
        // Move the (key, value) pair to the beginning of the list
        items.splice(items.begin(), items, cache[key]);
        return cache[key]->second;
    }

    void set(int key, int value) {
        // The key is not in the hash table
        if (cache.find(key) == cache.end()) {
            // If the cache is full then delete the least recently
            // used item, which is at the end of the list
            if (items.size() == capacity) {
                cache.erase(items.back().first);
                items.pop_back();
            }
            items.push_front(make_pair(key, value));
            cache[key] = items.begin();
        } else {
            // Update the value associated with the key
            cache[key]->second = value;
            // Move the (key, value) pair to the beginning of the list
            items.splice(items.begin(), items, cache[key]);
        }
    }
}

 

 

我的代码,时间是用自己设的time来记录的,超时了。

typedef struct Data
{
    int value;
    int time;
    Data(){}
    Data(int v, int t) : value(v), time(t){}
}Data;

class LRUCache{
public:
    LRUCache(int capacity) {
        t = 0;                //初始化时间
        c = capacity;         //初始化容量
    }
    
    int get(int key) {
        unordered_map<int, Data>::iterator it = record.find(key);
        if(it == record.end())
        {
            return -1;
        }
        else
        {
            it->second.time = t++;
            return it->second.value;
        }

    }
    
    void set(int key, int value) {
        if(record.find(key) != record.end())
        {
            record[key].value = value;
            record[key].time = t++;
            return;
        }
        if(record.size() == c)   //容量已经达到
        {
            unordered_map<int, Data>::iterator replace = record.begin();
            for(unordered_map<int, Data>::iterator it = record.begin(); it != record.end(); it++)
            {
                replace = (it->second.time < replace->second.time) ? it : replace;
            }
            record.erase(replace); //删掉时间最早的
        }

        Data newData(value, t);
        record[key] = newData;
        t++;
    }
private:
    unordered_map<int, Data> record;
    int c;
    int t;
};

 

posted @ 2015-05-06 09:52  匡子语  阅读(210)  评论(0编辑  收藏  举报