题解 | #设计LRU缓存结构#

设计LRU缓存结构

https://www.nowcoder.com/practice/5dfded165916435d9defb053c63f1e84

首先是使用何种数据结构?

不考虑时间复杂度的话用栈会非常清晰,新的入栈,旧的从栈底去除,更新的从栈中拿到栈顶即可。

但如果要考虑取值的时间复杂试为O(1)的话,我们可以使用map来解决。同时考虑更新值也为O(1)的话,就不能使用栈了,更新值会导致其余值的移动,所以考虑使用链表。

这样的话数据结构就确定了,使用map+list的形式。

其次是如何实现?

  • 首先是set添加元素:如果是新key,则创建新结点添加到链表尾部前方,并在map中注册(如果已达到容量需要从链表头部删除一个元素,并且从map中去除该key);如果是map中已有的key, 则更新值后拿到尾部前方

  • 其次是get访问元素:类似地,如果是新key,则返回-1;如果是map中已有的key,则拿到尾部前方

具体看代码:

struct node {
    int value;
    node* pre;
    node* suf;
    int key;
};

void deleteNode(node* mid) {
    mid->suf->pre = mid->pre;
    mid->pre->suf = mid->suf;
    delete mid;
    mid = nullptr;
}

void removeNode(node* mid) {
    mid->suf->pre = mid->pre;
    mid->pre->suf = mid->suf;
}

void addBeforeNode(node* mid, node* next) {
    mid->pre = next->pre;
    next->pre->suf = mid;
    mid->suf = next;
    next->pre = mid;
}

class Solution {
  private:
    map<int, node*> buffer_map;
    node* head;
    node* tail;
    int ele_n;
    int capacity;
  public:
    Solution(int capacity) : capacity(capacity) {
        // write code here
        ele_n = 0;
        // add the head
        head = new node();
        tail = new node();
        head->suf = tail;
        tail->pre = head;
    }

    void show() {
        node* tmp = head->suf;
        while (tmp->suf != nullptr) {
            cout << tmp->value << ",";
            tmp = tmp->suf;
        }
        cout << endl;
    }

    int get(int key) {
        // write code here
        if (buffer_map.count(key) == 0) { // 没有key信息
            return -1;
        } else { // 有key信息
            if (buffer_map[key] != tail->pre) { // 如果不在尾部
                // 取出节点
                removeNode(buffer_map[key]);
                // 拿到尾部
                addBeforeNode(buffer_map[key], tail);
            }
            return tail->pre->value;
        }

    }

    void set(int key, int value) {
        // write code here
        if (buffer_map.count(key) == 0) { // 新key
            if (ele_n == capacity) { // 已达到容量
                // 删除第一个节点
                buffer_map.erase(head->suf->key); // 从map中删除
                deleteNode(head->suf); // 从链表中删除
                ele_n--;
            }
            // 添加到链表尾部
            node* tmp = new node();
            tmp->key = key;
            tmp->value = value;
            addBeforeNode(tmp, tail);
            // 添加到map
            buffer_map[key] = tmp; // add key and node to map
            ele_n++;
        } else { // 已经存储的key
            if (buffer_map[key] != tail) { // 如果不在尾部
                // 更新值
                buffer_map[key]->value = value;
                // 取出节点
                removeNode(buffer_map[key]);
                // 拿到尾部
                addBeforeNode(buffer_map[key], tail);
            }
        }
    }
};

#刷题心得#
全部评论

相关推荐

尊嘟假嘟点击就送:加v细说,问题很大
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务