考点
题解
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 class LRUCache { private : struct Node { int key; int value; Node (int _key, int _value) : key (_key), value (_value) {} }; int capacity; list<Node> l; unordered_map<int , list<Node>::iterator> m; public : LRUCache (int _capacity) : capacity (_capacity) {} int get (int key) { auto it = m.find (key); if (it == m.end ()) return -1 ; int value = it->second->value; l.erase (it->second); l.emplace_front (key, value); m[key] = l.begin (); return value; } void put (int key, int value) { auto it = m.find (key); if (it == m.end ()) { if (capacity == 0 ) return ; if (m.size () == (unsigned long long )capacity) { m.erase (l.back ().key); l.pop_back (); } } else { l.erase (it->second); } l.emplace_front (key, value); m[key] = l.begin (); } };
思路
LRU又称为最近最少使用页面置换算法(Least Recently
Used),淘汰最早访问的页面
题目要求查找与增删节点时均要达到常量时间复杂度,很容易想到哈希表+链表的组合
无序哈希表在平均情况下的查找为常量时间复杂度,而有序哈希表的查找为对数时间复杂度,因为底层是红黑树
所以有以下思路:
每次访问/更新节点时,先将其从链表中删除,再将其插入到链表头部以代表最近访问
这样一来链表末尾节点自然是最早访问的了
因为只涉及到删除链表中节点、删除链表尾部节点和插入链表头部节点,使用双向链表较为方便;这里使用list
这一STL库来完成
使用哈希表来记录键与节点的映射关系,这样就能直接操控链表节点而不用去遍历寻找
数据结构设计如图所示