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 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
| class LFUCache { public: LFUCache(int capacity) : head(new Node(-1, 0, -1)), tail(new Node(-1, 0, INT_MAX)), size(0), capacity(capacity) { head->next = tail; tail->prev = head; } int get(int key) { if(capacity == 0) return -1; if(!map.count(key)) return -1; auto ret = map[key]->value; int oldc = map[key]->count++; if(oldc != map[key]->prev->count && oldc != map[key]->next->count) location.erase(oldc); else if(oldc == map[key]->prev->count && oldc != map[key]->next->count) location[oldc] = map[key]->prev; int c = oldc + 1; if(c >= map[key]->next->count) moveToNext(location[map[key]->next->count], map[key]); if(c == map[key]->next->count) moveToNext(location[c], map[key]); location[c] = map[key]; return ret; } void put(int key, int value) { if(capacity == 0) return; if(!map.count(key)) { if(++size > capacity) { --size; removeHead(); } addToHead(key, value); }else { map[key]->value = value; int oldc = map[key]->count++; if(oldc != map[key]->prev->count && oldc != map[key]->next->count) location.erase(oldc); else if(oldc == map[key]->prev->count && oldc != map[key]->next->count) location[oldc] = map[key]->prev; } auto c = map[key]->count; if(c >= map[key]->next->count) moveToNext(location[map[key]->next->count], map[key]); if(c == map[key]->next->count) moveToNext(location[c], map[key]); location[c] = map[key]; } private: struct Node { int key; int count; int value; Node* prev; Node* next; Node(int key, int value, int count = 1) : key(key), value(value), count(count) {} }; Node *head, *tail; int size, capacity; unordered_map<int, Node*> map; unordered_map<int, Node*> location; private: void exchangeNearbyNodes(Node* n1, Node* n2) { n1->next = n2->next; n2->next->prev = n1; n2->next = n1; n2->prev = n1->prev; n1->prev->next = n2; n1->prev = n2; } void removeHead() { if(head->next == tail) return; auto node = head->next; head->next->next->prev = head; head->next = head->next->next; map.erase(node->key); if(node->next->count != node->count) location.erase(node->count); delete node; } void addToHead(int key, int value) { auto node = new Node(key, value); node->next = head->next; head->next->prev = node; head->next = node; node->prev = head; map.emplace(key, node); } void isolatedNode(Node* node) { node->prev->next = node->next; node->next->prev = node->prev; } void moveToNext(Node* prev, Node* node) { isolatedNode(node); node->next = prev->next; node->prev = prev; prev->next->prev = node; prev->next = node; } };
|