Skip to content

Commit f1d1f91

Browse files
committed
0146. LRU Cache
1 parent f409b16 commit f1d1f91

File tree

4 files changed

+396
-0
lines changed

4 files changed

+396
-0
lines changed

markdown/0146. LRU Cache.md

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
### [146\. LRU Cache](https://leetcode.com/problems/lru-cache/)
2+
3+
> 我使用双向循环链表和 hashtable 完成了,这里有一个小细节就是 put 的时候也是访问,需要将对应的 Node 提取到 head 上。
4+
5+
Difficulty: **Medium**
6+
7+
8+
Design and implement a data structure for . It should support the following operations: `get` and `put`.
9+
10+
`get(key)` - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
11+
`put(key, value)` - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.
12+
13+
The cache is initialized with a **positive** capacity.
14+
15+
**Follow up:**
16+
Could you do both operations in **O(1)** time complexity?
17+
18+
**Example:**
19+
20+
```
21+
LRUCache cache = new LRUCache( 2 /* capacity */ );
22+
23+
cache.put(1, 1);
24+
cache.put(2, 2);
25+
cache.get(1); // returns 1
26+
cache.put(3, 3); // evicts key 2
27+
cache.get(2); // returns -1 (not found)
28+
cache.put(4, 4); // evicts key 1
29+
cache.get(1); // returns -1 (not found)
30+
cache.get(3); // returns 3
31+
cache.get(4); // returns 4
32+
```
33+
34+
35+
#### Solution
36+
37+
Language: **Java**
38+
39+
```java
40+
class LRUCache {
41+
42+
class LRUValue {
43+
int key;
44+
int value;
45+
LRUValue next; //链表下一个节点的key
46+
LRUValue pre;// 链表上一个节点的key
47+
48+
public LRUValue(int key, int value, LRUValue next, LRUValue pre) {
49+
this.key = key;
50+
this.value = value;
51+
this.next = next;
52+
this.pre = pre;
53+
}
54+
}
55+
56+
private Map<Integer, LRUValue> map = new HashMap<>();
57+
private int capacity;
58+
private LRUValue head;
59+
60+
public LRUCache(int capacity) {
61+
this.capacity = capacity;
62+
}
63+
64+
public int get(int key) {
65+
if (!map.containsKey(key)) {
66+
return -1;
67+
} else {
68+
LRUValue lruValue = map.get(key);
69+
if (lruValue != head) { // 如果获取的元素不是在头部,需要将该元素升级到头部
70+
promotionNode(lruValue);
71+
}
72+
return head.value;
73+
}
74+
}
75+
76+
public void put(int key, int value) {
77+
if (map.size() == 0) {
78+
LRUValue lruValue = new LRUValue(key, value, null, null);
79+
lruValue.next = lruValue;
80+
lruValue.pre = lruValue;
81+
head = lruValue;
82+
map.put(key, lruValue);
83+
} else {
84+
LRUValue targetValue = map.get(key);
85+
if (targetValue != null) {// 注意 put 也算是访问,需要把它提到 header
86+
if (targetValue != head) {
87+
promotionNode(targetValue);
88+
}
89+
targetValue.value = value;
90+
} else {
91+
if (map.size() >= capacity) {
92+
int removeKey = head.pre.key;
93+
head.pre = head.pre.pre;
94+
map.remove(removeKey);
95+
}
96+
LRUValue lruValue = new LRUValue(key, value, head, head.pre);
97+
map.put(key, lruValue);
98+
head.pre.next = lruValue;
99+
head.pre = lruValue;
100+
head = lruValue;
101+
}
102+
}
103+
}
104+
105+
private void promotionNode(LRUValue lruValue) {
106+
lruValue.pre.next = lruValue.next;
107+
lruValue.next.pre = lruValue.pre;
108+
head.pre.next = lruValue;
109+
lruValue.next = head;
110+
lruValue.pre = head.pre;
111+
head.pre = lruValue;
112+
head = lruValue;
113+
}
114+
}
115+
116+
/**
117+
* Your LRUCache object will be instantiated and called as such:
118+
* LRUCache obj = new LRUCache(capacity);
119+
* int param_1 = obj.get(key);
120+
* obj.put(key,value);
121+
*/
122+
```
123+
![](https://raw.githubusercontent.com/PicGoBed/PicBed/master/20190724010539.png)
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package leetcode._146_;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
/**
7+
* Created by zhangbo54 on 2019-07-23.
8+
*/
9+
class LRUCache {
10+
11+
class LRUValue {
12+
int key;
13+
int value;
14+
LRUValue next; //链表下一个节点的key
15+
LRUValue pre;// 链表上一个节点的key
16+
17+
public LRUValue(int key, int value, LRUValue next, LRUValue pre) {
18+
this.key = key;
19+
this.value = value;
20+
this.next = next;
21+
this.pre = pre;
22+
}
23+
}
24+
25+
private Map<Integer, LRUValue> map = new HashMap<>();
26+
private int capacity;
27+
private LRUValue head;
28+
29+
public LRUCache(int capacity) {
30+
this.capacity = capacity;
31+
}
32+
33+
public int get(int key) {
34+
if (!map.containsKey(key)) {
35+
return -1;
36+
} else {
37+
LRUValue lruValue = map.get(key);
38+
if (lruValue != head) { // 如果获取的元素不是在头部,需要将该元素升级到头部
39+
promotionNode(lruValue);
40+
}
41+
return head.value;
42+
}
43+
}
44+
45+
public void put(int key, int value) {
46+
if (map.size() == 0) {
47+
LRUValue lruValue = new LRUValue(key, value, null, null);
48+
lruValue.next = lruValue;
49+
lruValue.pre = lruValue;
50+
head = lruValue;
51+
map.put(key, lruValue);
52+
} else {
53+
LRUValue targetValue = map.get(key);
54+
if (targetValue != null) {// 注意 put 也算是访问,需要把它提到 header
55+
if (targetValue != head) {
56+
promotionNode(targetValue);
57+
}
58+
targetValue.value = value;
59+
} else {
60+
if (map.size() >= capacity) {
61+
int removeKey = head.pre.key;
62+
head.pre = head.pre.pre;
63+
map.remove(removeKey);
64+
}
65+
LRUValue lruValue = new LRUValue(key, value, head, head.pre);
66+
map.put(key, lruValue);
67+
head.pre.next = lruValue;
68+
head.pre = lruValue;
69+
head = lruValue;
70+
}
71+
}
72+
}
73+
74+
private void promotionNode(LRUValue lruValue) {
75+
lruValue.pre.next = lruValue.next;
76+
lruValue.next.pre = lruValue.pre;
77+
head.pre.next = lruValue;
78+
lruValue.next = head;
79+
lruValue.pre = head.pre;
80+
head.pre = lruValue;
81+
head = lruValue;
82+
}
83+
}
84+
85+
/**
86+
* Your LRUCache object will be instantiated and called as such:
87+
* LRUCache obj = new LRUCache(capacity);
88+
* int param_1 = obj.get(key);
89+
* obj.put(key,value);
90+
*/
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package leetcode._146_;
2+
3+
/**
4+
* Created by zhangbo54 on 2019-03-04.
5+
*/
6+
public class Main {
7+
public static void main(String[] args) {
8+
// LRUCache lruCache = new LRUCache(2);
9+
// lruCache.put(1, 1);
10+
// lruCache.put(2, 2);
11+
// System.out.println(lruCache.get(1));
12+
// lruCache.put(3, 3);
13+
// System.out.println(lruCache.get(2));
14+
// lruCache.put(4, 4);
15+
// System.out.println(lruCache.get(1));
16+
// System.out.println(lruCache.get(3));
17+
// System.out.println(lruCache.get(4));
18+
//
19+
//
20+
// System.out.println("------------");
21+
//
22+
// LRUCache lruCache2 = new LRUCache(2);
23+
// lruCache2.put(2, 1);
24+
// lruCache2.put(1, 1);
25+
// lruCache2.put(2, 3);
26+
// lruCache2.put(4, 1);
27+
// System.out.println(lruCache2.get(1));
28+
// System.out.println(lruCache2.get(2));
29+
//
30+
// System.out.println("------------");
31+
//
32+
// LRUCache lruCache3 = new LRUCache(2);
33+
// System.out.println(lruCache3.get(2));
34+
// lruCache3.put(2, 6);
35+
// System.out.println(lruCache3.get(1));
36+
// lruCache3.put(1, 5);
37+
// lruCache3.put(1, 2);
38+
// System.out.println(lruCache3.get(1));
39+
// System.out.println(lruCache3.get(2));
40+
//
41+
// System.out.println("------------");
42+
43+
LRUCache lruCache4 = new LRUCache(3);
44+
lruCache4.put(1, 1);
45+
lruCache4.put(2, 2);
46+
lruCache4.put(3, 3);
47+
lruCache4.put(4, 4);
48+
System.out.println(lruCache4.get(4));
49+
System.out.println(lruCache4.get(3));
50+
System.out.println(lruCache4.get(2));
51+
System.out.println(lruCache4.get(1));
52+
lruCache4.put(5, 5);
53+
System.out.println(lruCache4.get(1));
54+
System.out.println(lruCache4.get(2));
55+
System.out.println(lruCache4.get(3));
56+
System.out.println(lruCache4.get(4));
57+
System.out.println(lruCache4.get(5));
58+
}
59+
}
60+

0 commit comments

Comments
 (0)