146. LRU 缓存

56 阅读1分钟

学习对象初始化的方法

Node(int _key, int _value): key(_key), value(_value) {
    head = new Node();
    taile = new Node();
    ...
}

注意的几点,结构体定义结束后面+分号;
这道题主要考虑:双向链表、哈希表(unordered_map)
LRU类中成员变量有size、capacity、head、tail(虚拟头节点、虚拟尾节点)、unoredered_map<int, Node*>
在使用get时:

  • 命中,将该节点移动至头部
  • 未命中,返回-1 在使用put时:
  • 之前存在:只需要将node的value修改,并将该nodemove至头部
  • 之前不存在:new一个node节点,将该节点add至头部。同时size++,并需要考虑size是否超过即>capacity,超过则需要删除最后一个节点
    以上重复的一些操作可写一个函数:例如moveToHead、removeNode、addToHead
    其实moveToHead就是removeNode、addToHead加起来
struct Node {
    int key;
    int value;
    Node* prev;
    Node* next;
    Node(): key(0), value(0), prev(nullptr), next(nullptr) {}
    Node(int _key, int _value): key(_key), value(_value), prev(nullptr), next(nullptr) {}
};

class LRUCache {
private:
    unordered_map<int, Node*> cache;
    Node* head;
    Node* tail;
    int size;
    int capacity;
public:
    LRUCache(int _capacity): capacity(_capacity), size(0) {
        head = new Node();
        tail = new Node();
        head->next = tail;
        tail->prev = head;
    }
    
    int get(int key) {
        auto it = cache.find(key);
        // 未命中
        if(it == cache.end()) {
            return -1;
        }
        // 命中
        Node* node = it->second;
        moveToHead(node);
        return node->value; 
    }
    
    void put(int key, int value) {
        auto it = cache.find(key);
        // 之前不存在
        if(it == cache.end()) {
            // 创建一个node,并将该node添加至头部
            Node* node = new Node(key, value);
            cache[key] = node;
            addToHead(node);
            ++size;
            if(size > capacity) {
                // 删除尾部节点
                Node* tmp = tail->prev;
                cache.erase(tmp->key);
                tmp->prev->next = tail;
                tail->prev = tmp->prev;
                delete tmp;
                --size;
            }
        }
        // 之前存在
        else {
            Node* node = it->second;
            node->value = value;
            moveToHead(node);
        }
    }

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

    void addToHead(Node* node) {
        node->prev = head;
        node->next = head->next;
        head->next->prev = node;
        head->next = node;
    }

    void moveToHead(Node* node) {
        removeNode(node);
        addToHead(node);
    }

};

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache* obj = new LRUCache(capacity);
 * int param_1 = obj->get(key);
 * obj->put(key,value);
 */