Jack Li's Blog

0146.LRU Cache

struct Node {
    int key;
    int val;
    Node* next;
    Node* prev;
    Node(int key, int val) : key(key), val(val), next(nullptr), prev(nullptr){}
};

class LRUCache {
public:
    int cap;
    Node* head = new Node(-1, -1);
    Node* tail = new Node(-1, -1);

    unordered_map<int, Node*> kv;

    LRUCache(int capacity) {
        this->cap = capacity;
        head->next = tail;
        tail->prev = head;
    }

    void removeNode(Node* curr) {
        // prev -> curr -> next;
        Node* prev = curr->prev;
        Node* next = curr->next;
        prev->next = next;
        next->prev = prev;
    }

    void addNode(Node* curr) {
        // head -> next;
        Node* next = head->next;
        head->next = curr;
        curr->prev = head;
        curr->next = next;
        next->prev = curr;
    }
    
    // If not found, return -1
    // If found,
    //  1. Move to the head
    int get(int key) {
        if(kv.find(key) == kv.end()) return -1;
        
        Node* node = kv[key];
        removeNode(node);
        addNode(node);
        return node->val;
    }
    
    // If found, move to head
    // else
    //   if meet capacity, remove tail->prev and add newNode
    void put(int key, int value) {
        if(kv.find(key) != kv.end()){
            Node* node = kv[key];
            node->val = value;
            removeNode(node);
            addNode(node);
            return;
        }

        if(kv.size() == cap){
            Node* garbage = tail->prev;
            kv.erase(tail->prev->key);
            removeNode(tail->prev);
            delete garbage;
        }

        Node* newNode = new Node(key, value);
        addNode(newNode);
        kv[key] = newNode;
    }
};