• LeetCode | LRU Cache


    Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set.

    get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
    set(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

    关于题意:

    一开始以为LRU指的是在满的时候删除引用最少的节点。后来才发现是按访问时间来排序的最早的节点。

    读懂题意之后就比较简单了:

    1. 存储数据肯定是要用map的。

    2. 怎样构建这个按访问时间排序的列表呢?这个列表需要能够快速增删。链表当然就最好。如果按时间插入,那么在删除时是删除表头,增加是在表尾。

    3. 插入链表时,需要把原来的节点给删掉。链表删除需要在o(1),只能用双向链表。而且当知道key的时候,需要知道当前的对应的链表节点的指针。所以map存的value可以直接设成对应的链表节点。

    4.  当空间满的时候,知道了LRU的元素(表头),需要把这个元素从map中删除,所以list的节点需要知道对应的map的指针。

    事后诸葛亮。。。


    双头链表(doubly-linked lists)

    1 record DoublyLinkedNode {
    2     prev // A reference to the previous node
    3     next // A reference to the next node
    4     data // Data or a reference to data
    5  }
    6 record DoublyLinkedList {
    7      DoublyLinkedNode firstNode   // points to first node of list
    8       DoublyLinkedNode lastNode    // points to last node of list
    9  }
    1 function insertAfter(List list, Node node, Node newNode)
    2      newNode.prev  := node
    3      newNode.next  := node.next
    4      if node.next == null
    5          list.lastNode  := newNode
    6      else
    7          node.next.prev  := newNode
    8      node.next  := newNode
    1 function insertBefore(List list, Node node, Node newNode)
    2      newNode.prev  := node.prev
    3      newNode.next = node
    4      if node.prev == null
    5          list.firstNode  := newNode
    6      else
    7          node.prev.next  := newNode
    8      node.prev  := newNode
    1 function insertBeginning(List list, Node newNode)
    2      if list.firstNode == null
    3          list.firstNode  := newNode
    4          list.lastNode   := newNode
    5          newNode.prev  := null
    6          newNode.next  := null
    7      else
    8          insertBefore(list, list.firstNode, newNode)
    1 function insertEnd(List list, Node newNode)
    2      if list.lastNode == null
    3          insertBeginning(list, newNode)
    4      else
    5          insertAfter(list, list.lastNode, newNode)
     1 function remove(List list, Node node)
     2    if node.prev == null
     3        list.firstNode  := node.next
     4    else
     5        node.prev.next  := node.next
     6    if node.next == null
     7        list.lastNode  := node.prev
     8    else
     9        node.next.prev  := node.prev
    10    destroy node

    Circular doubly-linked lists

    1 function remove(List list, Node node)
    2      if node.next == node
    3          list.lastNode := null
    4      else
    5          node.next.prev := node.prev
    6          node.prev.next := node.next
    7          if node == list.lastNode
    8              list.lastNode := node.prev;
    9      destroy node

    Asymmetric doubly-linked list

    同样是两个指针,next指针还是指向下一个,但是pre指针存的是自己的地址(指针的指针)。

    特点:

    1. 单向遍历;

    2. 增删都是o(1);

    3. 只要节点存在,它的prev指针一定存在。

    1 function insertBefore(Node node, Node newNode)
    2      if node.prev == null
    3           error "The node is not in a list"
    4      newNode.prev  := node.prev
    5      atAddress(newNode.prev)  := newNode
    6      newNode.next  := node
    7      node.prev = addressOf(newNode.next)
    1 function insertAfter(Node node, Node newNode)
    2      newNode.next  := node.next
    3      if newNode.next != null
    4          newNode.next.prev = addressOf(newNode.next)
    5      node.next  := newNode
    6      newNode.prev  := addressOf(node.next)
    1 function remove(Node node)
    2      atAddress(node.prev)  := node.next
    3      if node.next != null
    4          node.next.prev = node.prev
    5      destroy node
     1 class LRUCache{
     2 public:
     3     struct Data {
     4         int val;
     5         map<int, list<Data>::iterator >::iterator it;
     6     };
     7     
     8     LRUCache(int capacity) {
     9         this->capacity = capacity;
    10     }
    11     
    12     int get(int key) {
    13         map<int, list<Data>::iterator >::iterator it = keyValues.find(key);
    14         if (it == keyValues.end()) {
    15             return -1;
    16         } else {
    17             int val = it->second->val;
    18             data.erase(it->second);
    19             Data d;
    20             d.val = val;
    21             d.it = it;
    22             data.push_front(d);
    23             keyValues[key] = data.begin();
    24             return val;
    25         }
    26     }
    27     
    28     void set(int key, int value) {
    29         map<int, list<Data>::iterator >::iterator it = keyValues.find(key);
    30         if (it == keyValues.end()) {
    31             if (data.size() >= capacity) {
    32                 keyValues.erase(data.back().it); //need to erase the map
    33                 data.pop_back(); 
    34             }
    35             Data d;
    36             d.val = value;
    37             data.push_front(d);
    38             keyValues[key] = data.begin();
    39             data.begin()->it = keyValues.find(key);
    40         } else {
    41             Data d;
    42             d.val = value;
    43             d.it = it;
    44             data.erase(it->second);
    45             data.push_front(d);
    46             keyValues[key] = data.begin();
    47         }
    48     }
    49     
    50 private:
    51     int capacity;
    52     list<Data> data;
    53     map<int, list<Data>::iterator > keyValues;
    54 };
  • 相关阅读:
    第二十课字符串
    数学归纳法:搞定循环与递归的钥匙
    11预处理命令下
    Xshell6无法连接上虚拟机的解决方法
    redis数据库常用命令
    redis使用get命令,中文乱码问题
    Ubuntu下redis的安装和简单操作
    启动hbase后,使用指令进入shell命令行模式时报错"wrong number of arguments (0 for 1)"
    启动hbase报错:“SLF4J: Class path contains multiple SLF4J bindings.”解决方法
    ./bin/hadoop 提示“没有那个文件或目录”解决方法
  • 原文地址:https://www.cnblogs.com/linyx/p/3666465.html
Copyright © 2020-2023  润新知