-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path146-lru-cache.cpp
106 lines (94 loc) · 3.34 KB
/
146-lru-cache.cpp
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
// Title: LRU Cache
// Description:
// Design a data structure that follows the constraints of a Least Recently Used (LRU) cache.
// Implement the LRUCache class:
// LRUCache(int capacity)
// Initialize the LRU cache with positive size capacity.
// int get(int key)
// Return the value of the key if the key exists, otherwise return -1.
// void put(int key, int value)
// Update the value of the key if the key exists.
// Otherwise, add the key-value pair to the cache.
// If the number of keys exceeds the capacity from this operation, evict the least recently used key.
// Follow up:
// Could you do get and put in O(1) time complexity?
// Link: https://leetcode.com/problems/lru-cache/
// Time complexity: O(1) for { get(key), put(key, value) }
// Space complexity: O(n)
struct LinkListNode {
LinkListNode *prev;
LinkListNode *next;
int key;
int value;
LinkListNode(int key, int value): prev(NULL), next(NULL), key(key), value(value) {}
};
class LRUCache {
private:
int capacity;
std::unordered_map<int, LinkListNode *> nodeLocation;
LinkListNode *dummyHead;
LinkListNode *dummyTail;
void removeNode(LinkListNode *node) {
// take the note out of its current position
node->prev->next = node->next;
node->next->prev = node->prev;
}
void appendNode(LinkListNode *node) {
// put the node at the last position
node->next = dummyTail;
node->prev = dummyTail->prev;
dummyTail->prev->next = node;
dummyTail->prev = node;
}
void renewNode(LinkListNode *node) {
// skip this step if the node is already the newest
if (node->next == dummyTail) return;
removeNode(node);
appendNode(node);
}
public:
LRUCache(int capacity): capacity(capacity) {
dummyHead = new LinkListNode(0xDEAD, 0);
dummyTail = new LinkListNode(0xBEEF, 0);
dummyHead->next = dummyTail;
dummyTail->prev = dummyHead;
}
int get(int key) {
if (nodeLocation.count(key) != 0) {
LinkListNode *node = nodeLocation[key];
renewNode(node);
return node->value;
} else {
return -1;
}
}
void put(int key, int value) {
if (nodeLocation.count(key) != 0) {
LinkListNode *node = nodeLocation[key];
renewNode(node);
node->value = value;
} else {
if (capacity > 0) {
// create a new node with the value
LinkListNode *node = new LinkListNode(key, value);
appendNode(node);
nodeLocation.emplace(key, node);
capacity--;
} else {
// take the first (oldest) note out and reuse it
LinkListNode *node = dummyHead->next;
nodeLocation.erase(node->key);
node->key = key;
node->value = value;
renewNode(node);
nodeLocation.emplace(key, node);
}
}
}
};
/**
* 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);
*/