题目 请你设计并实现一个满足 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) 的平均时间复杂度运行。
分析 为了满足平均$O(1)$的时间复杂度,采用哈希表+双链表的方式实现。其中哈希表用来查找指定的键,而双链表则用来维护访问时间,将最近访问过的值放在链表头,最久未使用的值放在队尾。
代码 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 class  LRUCache  {public :     LRUCache (int  cap): capacity (cap), size (0 ) {         head = new  DLinkedNode ();         tail = new  DLinkedNode ();         head->next = tail;         tail->prev = head;     }          int  get (int  key)   {         if  (cache.find (key) == cache.end ()) return  -1 ;         auto  node = cache[key];         move2head (node);         return  node->val;     }          void  put (int  key, int  value)   {         if  (cache.find (key) != cache.end ())         {             auto  node = cache[key];             node->val = value;             move2head (node);         }         else          {             if  (size == capacity)             {                                                   cache.erase (tail->prev->key);                                  tail->prev->val = value;                 tail->prev->key = key;                                  cache.emplace (key, tail->prev);                                  move2head (tail->prev);             }             else              {                 ++size;                 auto  node = new  DLinkedNode (key, value);                 add2head (node);                 cache.emplace (key, node);             }         }     }     ~LRUCache ()     {         delete  head;         delete  tail;     }private :     struct  DLinkedNode {         int  key, val;         DLinkedNode *prev;         DLinkedNode *next;         DLinkedNode (): key (0 ), val (0 ), prev (nullptr ), next (nullptr ) {}         DLinkedNode (int  k, int  v): key (k), val (v), prev (nullptr ), next (nullptr ) {}     };     void  add2head (DLinkedNode *node)      {         node->next = head->next;         head->next->prev = node;         head->next = node;         node->prev = head;     }     void  removeNode (DLinkedNode *node)      {         node->prev->next = node->next;         node->next->prev = node->prev;     }     void  move2head (DLinkedNode *node)      {         removeNode (node);         add2head (node);     }          unordered_map<int , DLinkedNode*> cache;     DLinkedNode *head;     DLinkedNode *tail;     int  capacity;     int  size; };