You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A computer has limited memory cache. If the cache is full, some contents need to be removed from cache to provide space for new content. However, which part of the cache should be removed? We hope to remove not so useful contents, while leaving useful contents untouched for future usage. So the question is, what is the criteria to determine if the data is _useful_ or not?
11
+
A computer has limited memory cache. If the cache is full, some contents need to be removed from cache to provide space for new content. However, which part of the cache should be removed? We hope to remove not so useful contents, while leaving useful contents untouched for future usage. So the question is, what are the criteria to determine if the data is _useful_ or not?
12
12
13
-
LRU (Least Recently Used) cache clean-up algorithm is a common strategy. According to the name, the latest used data should be _useful_. Hence, when the memory cache is full, we should priortize to remove those data that haven't been used for long are not useful.
13
+
LRU (Least Recently Used) cache clean-up algorithm is a common strategy. According to the name, the latest used data should be _useful_. Hence, when the memory cache is full, we should prioritize removing those data that haven't been used for long are not useful.
14
14
15
-
For example, an Android phone can run apps in the backgroud. If I opened in sequence: Settings, Phone Manager, and Calendar, their order in the background will be shown as following:
15
+
For example, an Android phone can run apps in the background. If I opened in sequence: Settings, Phone Manager, and Calendar, their order in the background will be shown as following:
16
16
17
17

18
18
@@ -22,7 +22,7 @@ If I switch to Settings now, Settings will be brought to the first:
22
22
23
23
Assume that my phone only allows me to open 3 apps simultaneously, then the cache is already full by now. If I open another app, Clock, then I have to close another app to free up space for Clock. Which one should be closed?
24
24
25
-
Accoording to LRU strategy, the lowest app, Phone Manager, should be closed, because it is the longest unused app. Afterwards, the newly opened app will be on the top:
25
+
According to LRU strategy, the lowest app, Phone Manager, should be closed, because it is the longest unused app. Afterwards, the newly opened app will be on the top:
26
26
27
27

28
28
@@ -34,10 +34,10 @@ LRU algorithm is actually about data structure design:
34
34
1. Take a parameter, `capacity`, as the maximum size; then
35
35
2. Implement two APIs:
36
36
*`put(key, val)`: to store key-value pair
37
-
*`get(key)`: return the value associated with the key; return -1 if key doesn't exist.
37
+
*`get(key)`: return the value associated with the key; return -1 if the key doesn't exist.
38
38
3. The time complexity for both `get` and `put` should be __O(1)__.
39
39
40
-
Let's use an example to understand how LRU algorithm works.
40
+
Let's use an example to understand how the LRU algorithm works.
41
41
42
42
```cpp
43
43
/* Cache capacity is 2 */
@@ -59,7 +59,7 @@ cache.put(3, 3);
59
59
// cache = [(3, 3), (1, 1)]
60
60
// Remarks: the memory capacity is full
61
61
// We need to remove some contents to free up space
62
-
// Removal will priortize longest unused data, which is at the tail
62
+
// Removal will prioritize longest unused data, which is at the tail
63
63
// Afterwards, insert the new data at the head
64
64
cache.get(2); // return -1 (not found)
65
65
// cache = [(3, 3), (1, 1)]
@@ -79,21 +79,21 @@ Through analysis of the above steps, if time complexity for `put` and `get` are
79
79
-_Fast Deletion_: If the cache is full, we need to delete the last element.
80
80
-_Fast Insertion_: We need to insert the data to the head upon each visit.
81
81
82
-
Which data structure can fulfill the above requirements? Hash table can search fast, but the data is unordered. Data in linked list is ordered, and can be inserted or deleted fast, but is hard to be searched. Combining these two, we can come up with a new data structure: __hash linked list__.
82
+
Which data structure can fulfill the above requirements? Hash table can search fast, but the data is unordered. Data in linked list is ordered, and can be inserted or deleted fast, but is hard to search. Combining these two, we can come up with a new data structure: __hash linked list__.
83
83
84
84
The core data structure of LRU cache algorithm is hash linked list, a combination of doubly linked list and hash table. Here is how the data structure looks:
The idea is simple - using hash table to provide the ability of fast earch to linked list. Think again about the previous example, isn't this data structure the perfect solution for LRU cache data structure?
88
+
The idea is simple - using a hash table to provide the ability of fast search to linked list. Think again about the previous example, isn't this data structure the perfect solution for LRU cache data structure?
89
89
90
90
Some audience may wonder, why doubly linked list? Can't single linked list work? Since key exists in hash table, why do we have to store the key-value pairs in linked list instead of values only?
91
91
92
-
The answers only afloat when we actually do it. We can only understand the rationale behind the design after we implement LRU algorithm ourselves. Let's look at the code.
92
+
The answers only afloat when we actually do it. We can only understand the rationale behind the design after we implement the LRU algorithm ourselves. Let's look at the code.
93
93
94
94
### 4. Implementation
95
95
96
-
A lot of programming languages has built-in hash linked list, or LRU-alike functions. To help understand the details of LRU algorithm, let's use Java to re-invent the wheel.
96
+
A lot of programming languages have built-in hash linked list, or LRU-alike functions. To help understand the details of the LRU algorithm, let's use Java to reinvent the wheel.
97
97
98
98
First, define the `Node` class of doubly linked list. Assuming both `key` and `val` are of type `int`.
99
99
@@ -115,7 +115,7 @@ class DoubleList {
115
115
// Add x at the head, time complexity O(1)
116
116
publicvoidaddFirst(Nodex);
117
117
118
-
// Delete node x in the linked list (x is guarenteed to exist)
118
+
// Delete node x in the linked list (x is guaranteed to exist)
119
119
// Given a node in a doubly linked list, time complexity O(1)
120
120
publicvoidremove(Nodex);
121
121
@@ -129,9 +129,9 @@ class DoubleList {
129
129
130
130
P.S. This is the typical interface of a doubly linked list. In order to focus on the LRU algorithm, we'll skip the detailed implementation of functions in this class.
131
131
132
-
Now we can answer the question, why we have to use doubly linked list. In order to delete a node, we not only need to get the pointer of the node itself, but also need to update the node before and the node after. Only using a doubly linked list, we can guarentee the time complexity is O(1).
132
+
Now we can answer the question, why we have to use a doubly linked list. In order to delete a node, we not only need to get the pointer of the node itself, but also need to update the node before and the node after. Only using a doubly linked list, we can guarantee the time complexity is O(1).
133
133
134
-
With the doubly linked list, we just need to use it in with hash table in LRU algorithm. Let's sort out the logic with pseudo code:
134
+
With the doubly linked list, we just need to use it in with a hash table in the LRU algorithm. Let's sort out the logic with pseudo code:
135
135
136
136
```java
137
137
// key associated with Node(key, val)
@@ -158,7 +158,7 @@ void put(int key, int val) {
158
158
delete the last node in the linked list;
159
159
delete the associated value in map;
160
160
}
161
-
inseart the new node x to the head;
161
+
insert the new node x to the head;
162
162
associate the new node x with key in map;
163
163
}
164
164
}
@@ -228,6 +228,6 @@ If the cache is full, we not only need to delete the last node, but also need to
228
228
229
229
Till now, you should have understood the idea and implementation of LRU algorithm. One common mistake is to update associated entries in the hash table when you deal with nodes in the linked list.
230
230
231
-
**To make algorithm clear! Subscribe to my WeChat blog labuladong, and find more easy-to-understand articles.**:
231
+
**Explanine the algorithms clearly! Subscribe to my WeChat blog labuladong, and find more easy-to-understand articles.**:
0 commit comments