Description

Difficulty: 2.5/5.0

URL: https://oj.leetcode.com/problems/lru-cache/

Solution

This problem requires us to implement a LRU cache that supports two operations: get(int key) and set(int key, int val). An unodered_map would suffice for random access with keys and a doubly linked list can allow us to update the order of least recently used in time. We use unordered_map to reach the corresponding node in the list in constant time and the val is also saved in the node.

class LRUnode{
public:
    LRUnode * next, * prev;
    int val;
    int key;
    LRUnode(int key, int val){
        this->key = key;
        this->val = val;
        next = prev = nullptr;
    }
};

class LRUCache{
    int capacity;
    unordered_map<int, LRUnode *>cache;
    LRUnode *head, *tail;
public:
    LRUCache(int capacity) {
        this->capacity = capacity;
        tail = new LRUnode(-1, -1);
        head = new LRUnode(-1, -1);
        head->next = tail;
        tail->prev = head;
    }
    
    int get(int key) {
        if (cache.find(key) != cache.end()){ //exist
            update(key, cache[key]->val);
            return cache[key]->val;
        }
        else
            return -1;
    }
    
    void set(int key, int val) {
        LRUnode *tp;
        if (cache.find(key) == cache.end()){ //key not exist
            if (!this->capacity){ //full
                // remove the least used key at the beginning of the list
                tp = head->next;
                head->next = head->next->next;
                head->next->prev = head;
                cache.erase(tp->key);
                
                tp->key = key;
                tp->val = val;                
            }
            else{ // not full
                tp = new LRUnode(key, val);
                this->capacity --;
            }
                
            // put the new key at the end
            cache[key] = tp;
            tp->next = tail;
            tp->prev = tail->prev;            
            tail->prev->next = tp;
            tail->prev = tp;
        }
        else // update existing key
            update(key, val);
    }
    void update(int key, int val){
        LRUnode * ptr = cache[key];
        ptr->val = val;
        
        //put it at the end of the list
        ptr->prev->next = ptr->next;
        ptr->next->prev = ptr->prev;
        
        ptr->next = tail;
        ptr->prev = tail->prev;
        tail->prev->next = ptr;
        tail->prev = ptr;
    }
};

Comments