-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLRU Cache.cpp
More file actions
101 lines (89 loc) · 3.1 KB
/
LRU Cache.cpp
File metadata and controls
101 lines (89 loc) · 3.1 KB
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
// Problem: LRU Cache
// Design a data structure that supports the following operations in O(1):
// - get(key): Return the value if present, else -1
// - put(key, value): Insert/Update the value. If capacity is exceeded, evict the least recently used (LRU) item.
//
// Approach:
// 1. Use a **Doubly Linked List (DLL)** + **HashMap**.
// - DLL maintains order of usage: most recently used (MRU) at the front, LRU at the back.
// - HashMap (key → DLL node) provides O(1) access to nodes.
// 2. Operations:
// - get(key):
// • If key exists: move the node to front (MRU) and return value.
// • Else return -1.
// - put(key, value):
// • If key exists: remove old node, insert new node at front.
// • If capacity full: remove node before dummyTail (LRU), erase from map.
// • Insert new node at front, update map.
// 3. Helper functions:
// - addToFront(node): Insert node right after dummyHead.
// - removeNode(node): Remove a node from DLL.
//
// Time Complexity: O(1) for both get and put
// Space Complexity: O(capacity)
class LRUCache {
public:
class DLLNode {
public:
int k, v;
DLLNode* prevNode;
DLLNode* nextNode;
DLLNode(int key, int value) {
this->k = key;
this->v = value;
prevNode = nextNode = nullptr;
}
};
DLLNode* dummyHead = new DLLNode(-1, -1);
DLLNode* dummyTail = new DLLNode(-1, -1);
int capacity;
unordered_map<int, DLLNode*> cache; // key -> node pointer
LRUCache(int cap) {
capacity = cap;
dummyHead->nextNode = dummyTail;
dummyTail->prevNode = dummyHead;
}
// Insert node right after dummyHead (marking it MRU)
void addToFront(DLLNode* newNode) {
DLLNode* temp = dummyHead->nextNode;
newNode->nextNode = temp;
newNode->prevNode = dummyHead;
dummyHead->nextNode = newNode;
temp->prevNode = newNode;
}
// Remove any node from DLL
void removeNode(DLLNode* node) {
DLLNode* prevTemp = node->prevNode;
DLLNode* nextTemp = node->nextNode;
prevTemp->nextNode = nextTemp;
nextTemp->prevNode = prevTemp;
}
int get(int key) {
if (cache.find(key) != cache.end()) {
DLLNode* targetNode = cache[key];
int value = targetNode->v;
// Move node to front (MRU)
cache.erase(key);
removeNode(targetNode);
addToFront(targetNode);
cache[key] = dummyHead->nextNode;
return value;
}
return -1;
}
void put(int key, int value) {
if (cache.find(key) != cache.end()) {
DLLNode* existing = cache[key];
cache.erase(key);
removeNode(existing);
}
if (cache.size() == capacity) {
// Remove LRU node (just before dummyTail)
cache.erase(dummyTail->prevNode->k);
removeNode(dummyTail->prevNode);
}
// Insert new node at front (MRU)
addToFront(new DLLNode(key, value));
cache[key] = dummyHead->nextNode;
}
};