Skip to content

leetcode 146. LRU 缓存机制

我的解题

使用标准库的linked list

#include <bits/stdc++.h>
using namespace std;

//class Node
//{
//public:
//  int key, val;
//  Node *next { nullptr }, *prev { nullptr };
//  Node(int k, int v) :
//                  key { k }, val { v }
//  {
//
//  }
//};

class LRUCache
{
    using Node = pair<int, int>; // key, value
    list<Node> cache;
    unordered_map<int, Node*> index; // key node
    int capacity;
public:
    LRUCache(int capacity) :
                    capacity { capacity }
    {

    }
    /**
     *
     * @param key
     * @return
     */
    int get(int key)
    {
        if (index.count(key))
        {
            makeRecently(key);
            return cache.front().second;
        }
        else
        {
            return -1;
        }
    }
    /**
     *
     * @param key
     * @param value
     */
    void put(int key, int value)
    {
        if (index.count(key))
        {
            deleteKey(key);
            addRecently(key, value);
        }
        else
        {
            if (capacity == cache.size())
            {
                removeLeastRecently();
            }
            addRecently(key, value);
        }
    }

private:
    /**
     * @brief 将key对应的节点,放到队首
     *
     * @param key
     */
    void makeRecently(int key)
    {
        if (index.count(key))
        {
            Node n = *(index[key]);
            cache.remove(n);
            cache.push_front(n);
            index[key] = &cache.front();
        }
    }

    /* 添加最近使用的元素 */
    void addRecently(int key, int val)
    {
        cache.emplace_front(key, val);
        // 别忘了在 map 中添加 key 的映射
        index[key] = &cache.front();
    }

    void deleteKey(int key)
    {
        if (index.count(key))
        {
            Node* x = index[key];
            // 从链表中删除
            cache.remove(*x);
            // 从 map 中删除
            index.erase(key);
        }
    }
    /* 删除最久未使用的元素 */
    void removeLeastRecently()
    {
        int key = cache.back().first;
        cache.pop_back(); // 删除最后一个元素
        // 同时别忘了从 map 中删除它的 key
        index.erase(key);
    }
};

/**
 * 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);
 */
// Driver code
int main()
{

    Solution solu;
    vector<int> nums = { 1, 3, 5, 4, 7 };
    return 0;
}
// g++ test.cpp --std=c++11 -pedantic -Wall -Wextra

超时。

自定义的double linked list

#include <bits/stdc++.h>
using namespace std;

class Node
{
public:
    int key { 0 }, val { 0 };
    Node *next { nullptr }, *prev { nullptr };
    Node(int k, int v) :
                    key { k }, val { v }
    {

    }
    Node() = default;
};
/**
 * @brief 双端链表
 *
 */
class DoubleLinkedList
{
    Node m_head, m_tail; // 使用伪头部和伪尾部节点,避免冗杂的空判断
    int m_size { 0 }; // 节点个数

public:
    DoubleLinkedList()
    {
        m_head.next = &m_tail;
        m_tail.prev = &m_head;
    }

    int size()
    {
        return m_size;
    }

    Node* emplace_front(int key, int val)
    {
        Node *n = new Node { key, val };
        Node *next = m_head.next;
        next->prev = n;

        n->prev = &m_head;
        n->next = next;

        m_head.next = n;

        ++m_size;
        return n;
    }
    /**
     * @brief 将节点n,移到头节点
     *
     * @param n
     */
    void move_to_head(Node *n)
    {
        do_unlink(n);
        insert(&m_head, n);
    }
    void unlink(Node *n)
    {
        if (m_size > 0)
        {
            do_unlink(n);
            --m_size;
        }
    }
    void erase(Node *n)
    {
        unlink(n);
        delete n;
    }
    Node* back()
    {
        if (m_size)
        {
            return m_tail.prev;
        }
        else
        {
            return nullptr;
        }
    }
private:
    /**
     * @brief 将节点n从链表中移除
     *
     * @param n
     */
    void do_unlink(Node *n)
    {
        Node *prev = n->prev;

        Node *next = n->next;

        prev->next = next;

        next->prev = prev;
    }
    /**
     * @brief 将node插入到prev 之后
     *
     * @param prev
     * @param n
     */
    void insert(Node *prev, Node *n)
    {
        Node *next = prev->next;
        next->prev = n;
        prev->next = n;

        n->next = next;
        n->prev = prev;
    }
};

class LRUCache
{
    DoubleLinkedList cache;
    unordered_map<int, Node*> index; // key node
    int capacity;
public:
    LRUCache(int capacity) :
                    capacity { capacity }
    {

    }
    /**
     *
     * @param key
     * @return
     */
    int get(int key)
    {
        if (index.count(key))
        {
            Node *n = index[key];
            cache.move_to_head(n);
            return n->val;
        }
        else
        {
            return -1;
        }
    }
    /**
     *
     * @param key
     * @param value
     */
    void put(int key, int value)
    {
        if (index.count(key))
        {
            Node *n = index[key];
            cache.move_to_head(n);
            n->val = value;
        }
        else
        {
            Node *n { nullptr }; // 指向此次新增的节点
            if (capacity == cache.size()) // 缓存空间满了
            {
                n = cache.back(); // 复用最后一个节点的空间
                index.erase(n->key); // 更新索引: 将原来的key删除
                cache.move_to_head(n); // 移到头
                n->key = key;
                n->val = value;
            }
            else
            {
                n = cache.emplace_front(key, value);
            }
            index[key] = n; // 更新索引
        }
    }
};

/**
 * 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);
 */
// Driver code
int main()
{

    Solution solu;
    vector<int> nums = { 1, 3, 5, 4, 7 };
    return 0;
}
// g++ test.cpp --std=c++11 -pedantic -Wall -Wextra