July 21, 2022
146. LRU Cache #LinkedList
題目 LeetCode: 146. LRU Cache
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.The functions get
and put
must each run in O(1)
average time complexity.
想法 基本上就是操作 linked list 在存取 key 時就把 key 的 node 移動到 head 要把東西丟掉就從尾巴 stl 有 std::list
可以使用不過在移動 node 時,由於 c++ ref 上並沒有寫明假如在同一個 list 上是否可以 splice,所以這裡是先刪除再加入 Ptr Code 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
121
122
123
124
125
126
127
struct Node {
Node* prev = nullptr ;
Node* next = nullptr ;
int data = 0 ;
Node(int data = 0 ): data(data) {}
};
// linkNode link a->b
inline void linkNode (Node* a, Node* b) {
a->next = b;
b->prev = a;
}
// linkNode link a->b->c
inline void linkNode (Node* a, Node* b, Node* c) {
linkNode(a, b);
linkNode(b, c);
}
class LinkList {
private :
// init: head -> tail
Node* head_;
Node* tail_;
int size_ = 0 ;
public :
// Remove copy operation
LinkList(const LinkList&) = delete ;
LinkList& operator =(const LinkList&) = delete ;
LinkList(): head_(new Node()), tail_(new Node()){
head_->next = tail_;
tail_->prev = head_;
}
~LinkList() {
auto cur = head_;
while (cur != nullptr ) {
auto tmp = cur;
cur = cur->next;
delete tmp;
}
}
Node* pushHead (int data) {
// before: head->n1
// after: head->n0->n1
auto n0 = new Node(data);
linkNode(head_, n0, head_->next);
++size_;
return n0;
}
void nodeToHead (Node* n) {
// before: ..n1->n->n0..
// after: head->n->h0..
linkNode(n->prev, n->next);
linkNode(head_, n, head_->next);
}
int popTail () {
// before: n1->n0->tail
// after: n1->tail;
auto n = tail_->prev;
linkNode(n->prev, n->next);
--size_;
int tmp = n->data;
delete n;
return tmp;
}
int size () const {
return size_;
}
};
class LRUCache {
public :
LRUCache(int capacity): sizeLimit_(capacity), cache_(1e4 + 2 ) {
}
int get (int key) {
auto & pack = cache_[key];
if (pack.node == nullptr ) {
return -1 ;
}
queue_.nodeToHead(pack.node);
return pack.value;
}
void put (int key, int value) {
auto & pack = cache_[key];
if (pack.node != nullptr ) {
queue_.nodeToHead(pack.node);
pack.value = value;
return ;
}
pack.node = queue_.pushHead(key);
pack.value = value;
if (queue_.size() > sizeLimit_) {
int removeKey = queue_.popTail();
cache_[removeKey].node = nullptr ;
}
}
private :
int sizeLimit_;
LinkList queue_;
struct Pack {
Node* node = nullptr ;
int value;
};
vector<Pack> cache_;
};
std::list
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
class LRUCache {
public :
LRUCache(int capacity) : sizeLimit_(capacity), cache_(1e4 + 2 ) {
}
int get (int key) {
auto & pack = cache_[key];
if (pack.null) {
return -1 ;
}
// move node to front
queue_.erase(pack.node);
queue_.push_front(key);
pack.node = queue_.begin();
return pack.value;
}
void put (int key, int value) {
auto & pack = cache_[key];
if (!pack.null) {
// move node to front
queue_.erase(pack.node);
queue_.push_front(key);
pack.node = queue_.begin();
pack.value = value;
return ;
}
queue_.push_front(key);
pack.node = queue_.begin();
pack.value = value;
pack.null = false ;
if (queue_.size() > sizeLimit_) {
int removeKey = queue_.back();
queue_.pop_back();
cache_[removeKey].null = true ;
}
}
private :
int sizeLimit_;
list<int > queue_;
struct Pack {
bool null = true ;
list<int >::iterator node;
int value;
};
vector<Pack> cache_;
};