力扣刷题6-LRU缓存

70 阅读2分钟
LRU缓存

题解思路:O(1) map + DLinkNode(双端队列) map<int, DLinkNode *> map;

get(int key):如果key存在,返回val,并move节点到队头;否则,返回-1

void put(int key, int value): 如果key存在,更新map中val,并move节点到对头;

如果key不存在,插入节点Node到队头,插入map,size++;判断size 是否超过阈值,如果超过,删除队尾元素

146 LRU

实现 LRUCache 类:

  • LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
  • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。

// 双向链表
struct DLinkNode {
  int key, val;
  DLinkNode *pre;
  DLinkNode *next;

  DLinkNode() : key(0), val(0), pre{nullptr}, next{nullptr} {};

  DLinkNode(int _key, int _val) : key(_key), val(_val), pre{nullptr}, next{nullptr} {}
};

class LRUCache {
private:
  map<int, DLinkNode *> map;
  DLinkNode *head;
  DLinkNode *tail;
  int size;
  int capacity;
public:
  LRUCache(int capacity) {
    this->capacity = capacity;
    size = 0;
    head = new DLinkNode();
    tail = new DLinkNode();
    head->next = tail;
    tail->pre = head;
  }

  void addToHead(DLinkNode *p) {
    DLinkNode *q = head->next;
    p->pre = head;
    p->next = q;
    q->pre = p;
    head->next = p;
  }

  void removeNode(DLinkNode *p) {
    p->pre->next = p->next;
    p->next->pre = p->pre;
  }

  void moveToHead(DLinkNode *p) {
    removeNode(p);
    addToHead(p);
  }

  DLinkNode *removeTail() {
    DLinkNode *removed = tail->pre;
    removeNode(removed);
    return removed;
  }

  int get(int key) {
    int res = -1;
    if (map.count(key)) {
      res = map[key]->val;
      DLinkNode *p = map[key];
      moveToHead(p);
    }
    return res;
  }

  void put(int key, int value) {
    if (map.count(key)) { //缓存已存在key,更新val并且移动node到链表头部
      DLinkNode *p = map[key];
      p->val = value;
      moveToHead(p);
    } else { //缓存不存在key,新node插入到链表头部,hashmap中插入新node key
      DLinkNode *p = new DLinkNode(key, value);
      map[key] = p;
      size++;
      addToHead(p);
      if (size > capacity) { //超过链表容量,移除链表尾部指针
        auto removed = removeTail();
        map.erase(removed->key);
        delete removed;
        size--;
      }
    }
  }
};