Leetcode:146.LRU缓存机制

146. LRU缓存机制

运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put

获取数据 get(key) - 如果关键字 (key) 存在于缓存中,则获取关键字的值(总是正数),否则返回 -1。
写入数据 put(key, value) - 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字/值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。

进阶:

你是否可以在 O(1) 时间复杂度内完成这两种操作?

示例:

LRUCache cache = new LRUCache( 2 /* 缓存容量 */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 该操作会使得关键字 2 作废
cache.get(2); // 返回 -1 (未找到)
cache.put(4, 4); // 该操作会使得关键字 1 作废
cache.get(1); // 返回 -1 (未找到)
cache.get(3); // 返回 3
cache.get(4); // 返回 4

解析:

使用双向链表来表示最近使用的队列(方便节点移动和插入),同时使用map索引来快速访问任意节点。

struct DLinkedNode{
    int key, value;
    DLinkedNode *pre, *next;
    DLinkedNode():key(0), value(0), pre(nullptr), next(nullptr){}
    DLinkedNode(int key, int value):key(key), value(value), pre(nullptr), next(nullptr){}
};

class LRUCache {
private:
    unordered_map<int, DLinkedNode*> cache;
    DLinkedNode *head, *tail;
    int size;
    int capacity;

public:
    LRUCache(int capacity):capacity(capacity),size(0) {
        head = new DLinkedNode();
        tail = new DLinkedNode();
        head->next = tail;
        tail->pre = head;
    }
    
    int get(int key) {
        if(!cache.count(key)) return -1;
        moveToHead(cache[key]);

        return cache[key]->value;
    }
    
    void put(int key, int value) {
        if(cache.count(key)){
            cache[key]->value = value;
            moveToHead(cache[key]);
            return;
        }
        if(size==capacity){
            DLinkedNode* cur = removeTail();
            cache.erase(cur->key);
            --size;
        }
        cache[key] = new DLinkedNode(key, value);
        moveToHead(cache[key]);++size;
       
        return;
    }

    void moveToHead(DLinkedNode *node){
        if(node->next) {//如果是旧的节点,需要将此节点原位置的前后节点连接起来
            node->pre->next = node->next;
            node->next->pre = node->pre;
        }
        head->next->pre = node;
        node->pre = head;
        node->next = head->next;
        head->next = node;
    }
    DLinkedNode* removeTail(){
        DLinkedNode* cur = tail->pre;
        
        tail->pre = cur->pre;
        cur->pre->next=tail;
        return cur;
    }
};

/**
 * 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);
 */
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。