LeetCode 146. LRU Cache
高频题,需要用unordered_map和list,做到O(1)。unordered_map: key->iterator,而list的元素是pair(key,value) 是有好处的,这样我们就不用另外一个hashtable来记录 key->val。
至于为何要将key和value的pair作为list的元素,而不是仅仅用value作为list的元素,是因为在超过cap的时候,我们可以用 l.back().first O(1) 得到key然后从unordered_map里删除key与iterator的对应关系。
需要注意的一点是,list用了splice改变了节点的位置,但是iterator并不会失效,这也代表unordered_map不需要进行更新。(可以把iterator当成指针方便理解)
class LRUCache { public: int cap; // recent visit will be moved to the head list<pair<int,int>> l; // pair(key,val) unordered_map<int,list<pair<int,int>>::iterator> m; // key -> iterator in list LRUCache(int capacity) { cap = capacity; } int get(int key) { if (!m.count(key)) return -1; int res=(*m[key]).second; l.splice(l.begin(), l, m[key]); //move key to the first return res; } void put(int key, int value) { if (m.count(key)) l.erase(m[key]); l.push_front(make_pair(key,value)); m[key] = l.begin(); if (l.size()>cap){ m.erase(l.back().first); l.pop_back(); } } }; /** * 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); */
本题也可以用一个 unordered_map,key -> <value, list iterator>,list 里按照顺序只存放 key。
C++ list splice
第一个 iterator 表示插入的起始位置,该 iterator 在 splice 后不会失效,依旧指向原来的元素。
第二个 iterator 如果原本也是指向当前 list,则不会失效,splice 后依旧指向原来的元素。如果不是,则会失效。
| single element (2) |
void splice (const_iterator position, list& x, const_iterator i); void splice (const_iterator position, list&& x, const_iterator i); |
|---|
int main() { list<int> l; l.push_back(1); l.push_back(2); l.push_back(3); auto it=l.begin(); advance(it,2); // point 3 auto it2=l.begin(); // point 1 l.splice(it2,l,it); for (auto x:l) cout<<x<<' '; // 3 1 2 cout << *it; // point 3 cout << *it2; // point 1 return 0; }

浙公网安备 33010602011771号