Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit ecb45d1

Browse files
Merge pull request #50 from zhng1456/dev
add solution 146 with java
2 parents b5f5e6a + d8abf3e commit ecb45d1

File tree

2 files changed

+207
-0
lines changed

2 files changed

+207
-0
lines changed

‎solution/146.Lru Cache/README.md‎

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
## LRU缓存
2+
### 题目描述
3+
4+
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。
5+
获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。
6+
写入数据 put(key, value) - 如果密钥不存在,则写入其数据值。当缓存容量达到上限时,它应该在写入新数据之前删除最近最少使用的数据值,从而为新的数据值留出空间。
7+
8+
示例:
9+
```
10+
LRUCache cache = new LRUCache( 2 /* 缓存容量 */ );
11+
12+
cache.put(1, 1);
13+
cache.put(2, 2);
14+
cache.get(1); // 返回 1
15+
cache.put(3, 3); // 该操作会使得密钥 2 作废
16+
cache.get(2); // 返回 -1 (未找到)
17+
cache.put(4, 4); // 该操作会使得密钥 1 作废
18+
cache.get(1); // 返回 -1 (未找到)
19+
cache.get(3); // 返回 3
20+
cache.get(4); // 返回 4
21+
```
22+
23+
### 解法
24+
用一个哈希表和一个双向链表来实现
25+
- 哈希表保存每个节点的地址
26+
- 链表头表示上次访问距离现在时间最短,尾部表示最近访问最少
27+
- 访问节点,若节点存在,要把该节点放到链表头
28+
- 插入时要考虑是否超过容量
29+
30+
```java
31+
//双向链表的节点
32+
class Node{
33+
public int key;
34+
public int val;
35+
public Node pre;//指向前面的指针
36+
public Node next;//指向后面的指针
37+
public Node(int key,int value){
38+
this.val = value;
39+
this.key = key;
40+
}
41+
}
42+
class LRUCache {
43+
int capacity;//容量
44+
Node head;//双向链表的头,维护这个指针,因为set,get时需要在头部操作
45+
Node end;//双向链表的尾,set时,要是满了,需要将链表的最后一个节点remove
46+
HashMap<Integer,Node> map = new HashMap<Integer,Node>();//hash表
47+
public LRUCache(int capacity) {
48+
this.capacity = capacity;
49+
}
50+
//添加,删除尾部,插入头部的操作
51+
public void remove(Node node){
52+
Node cur = node;
53+
Node pre = node.pre;
54+
Node post = node.next;
55+
if(pre == null){//说明cur是头部节点
56+
head = post;
57+
}
58+
else pre.next = post;//更新指针,删除
59+
if(post == null){//说明cur是最后的节点
60+
end = pre;
61+
}
62+
else post.pre = pre;
63+
}
64+
public void setHead(Node node){
65+
//直接插入
66+
node.next = head;
67+
node.pre = null;
68+
if(head != null) head.pre = node;//防止第一次插入时为空
69+
head = node;
70+
if(end==null) end = node;
71+
}
72+
public int get(int key) {
73+
if(map.containsKey(key)){
74+
//需要把对应的节点调整到头部
75+
Node latest = map.get(key);
76+
remove(latest);
77+
setHead(latest);
78+
//返回value
79+
return latest.val;
80+
}
81+
else return -1;
82+
}
83+
84+
public void put(int key, int value) {
85+
if(map.containsKey(key)){//这个key原来存在
86+
//只需要把key对应的node提到最前面,更新value
87+
Node oldNode = map.get(key);
88+
oldNode.val = value;
89+
remove(oldNode);
90+
setHead(oldNode);
91+
}
92+
else{
93+
//这个key原来不存在,需要重新new出来
94+
Node newNode = new Node(key,value);
95+
//接下来要考虑容量
96+
if(map.size() < capacity){
97+
setHead(newNode);
98+
map.put(key, newNode);
99+
}
100+
else{
101+
//容量不够,需要先将map中,最不常使用的那个删除了删除
102+
map.remove(end.key);
103+
//接下来更新双向链表
104+
remove(end);
105+
setHead(newNode);
106+
//放入新的
107+
map.put(key, newNode);
108+
}
109+
}
110+
}
111+
}
112+
113+
/**
114+
* Your LRUCache object will be instantiated and called as such:
115+
* LRUCache obj = new LRUCache(capacity);
116+
* int param_1 = obj.get(key);
117+
* obj.put(key,value);
118+
*/
119+
```

‎solution/146.Lru Cache/Solution.java‎

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//双向链表的节点
2+
class Node{
3+
public int key;
4+
public int val;
5+
public Node pre;//指向前面的指针
6+
public Node next;//指向后面的指针
7+
public Node(int key,int value){
8+
this.val = value;
9+
this.key = key;
10+
}
11+
}
12+
class LRUCache {
13+
int capacity;//容量
14+
Node head;//双向链表的头,维护这个指针,因为set,get时需要在头部操作
15+
Node end;//双向链表的尾,set时,要是满了,需要将链表的最后一个节点remove
16+
HashMap<Integer,Node> map = new HashMap<Integer,Node>();//hash表
17+
public LRUCache(int capacity) {
18+
this.capacity = capacity;
19+
}
20+
//添加,删除尾部,插入头部的操作
21+
public void remove(Node node){
22+
Node cur = node;
23+
Node pre = node.pre;
24+
Node post = node.next;
25+
if(pre == null){//说明cur是头部节点
26+
head = post;
27+
}
28+
else pre.next = post;//更新指针,删除
29+
if(post == null){//说明cur是最后的节点
30+
end = pre;
31+
}
32+
else post.pre = pre;
33+
}
34+
public void setHead(Node node){
35+
//直接插入
36+
node.next = head;
37+
node.pre = null;
38+
if(head != null) head.pre = node;//防止第一次插入时为空
39+
head = node;
40+
if(end==null) end = node;
41+
}
42+
public int get(int key) {
43+
if(map.containsKey(key)){
44+
//需要把对应的节点调整到头部
45+
Node latest = map.get(key);
46+
remove(latest);
47+
setHead(latest);
48+
//返回value
49+
return latest.val;
50+
}
51+
else return -1;
52+
}
53+
54+
public void put(int key, int value) {
55+
if(map.containsKey(key)){//这个key原来存在
56+
//只需要把key对应的node提到最前面,更新value
57+
Node oldNode = map.get(key);
58+
oldNode.val = value;
59+
remove(oldNode);
60+
setHead(oldNode);
61+
}
62+
else{
63+
//这个key原来不存在,需要重新new出来
64+
Node newNode = new Node(key,value);
65+
//接下来要考虑容量
66+
if(map.size() < capacity){
67+
setHead(newNode);
68+
map.put(key, newNode);
69+
}
70+
else{
71+
//容量不够,需要先将map中,最不常使用的那个删除了删除
72+
map.remove(end.key);
73+
//接下来更新双向链表
74+
remove(end);
75+
setHead(newNode);
76+
//放入新的
77+
map.put(key, newNode);
78+
}
79+
}
80+
}
81+
}
82+
83+
/**
84+
* Your LRUCache object will be instantiated and called as such:
85+
* LRUCache obj = new LRUCache(capacity);
86+
* int param_1 = obj.get(key);
87+
* obj.put(key,value);
88+
*/

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /