146. LRU Cache

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
class LRUCache {

private static class Node {
private final int key; // 淘汰元素时使用
private int val;
private Node prev;
private Node next;

public Node(int key, int val) {
this.key = key;
this.val = val;
}
}

private final int capacity;
private final Map<Integer, Node> cache;
private final Node dummyHead;
private final Node dummyTail;

public LRUCache(int capacity) {
this.capacity = capacity;
this.cache = new HashMap<>();
this.dummyHead = new Node(-1, -1);
this.dummyTail = new Node(-1, -1);
this.dummyHead.next = this.dummyTail;
this.dummyTail.prev = this.dummyHead;
}

public int get(int key) {
Node node = cache.get(key);
if (node == null) {
return -1;
}

moveToHead(node);
return node.val;
}

private void removeNode(Node node) {
Node prev = node.prev, next = node.next;
prev.next = next;
next.prev = prev;
node.prev = null;
node.next = null;
}

private void addToHead(Node node) {
Node head = dummyHead.next;
dummyHead.next = node;
head.prev = node;
node.prev = dummyHead;
node.next = head;
}

private void moveToHead(Node node) {
removeNode(node);
addToHead(node);
}

public void put(int key, int value) {
if (capacity == 0) {
return;
}

Node node = cache.get(key);
if (node != null) {
node.val = value;
moveToHead(node);
return;
}

node = new Node(key, value);
cache.put(key, node);
addToHead(node);

if (cache.size() > capacity) {
Node tail = dummyTail.prev;
cache.remove(tail.key);
removeNode(tail);
}
}
}

注意是双向链表,移动节点时需要注意修改前后两个节点的指针,注意 map 与链表需要同步修改。

References

146. LRU Cache
面试题 16.25. LRU 缓存
剑指 Offer II 031. 最近最少使用缓存