用双向链表实现一个LRU cache,这里自定义越靠近链表头的node,在越近的时间使用过。支持两个操作——get和set:
这道题使用两个数据结构,doubly linked list 和 hashmap.
怎么想的:
注意删值的时候要先从map删,再删node。
Time: O(1) for both put and get; Space: O(capacity)
class Node {
int key;
int val;
Node prev;
Node next;
public Node(int key, int val) {
this.key = key;
this.val = val;
}
}
class LRUCache {
Node head;
Node tail;
Map<Integer, Node> map;
int capacity;
int size;
public LRUCache(int capacity) {
head = new Node(0, 0);
tail = new Node(0, 0);
head.next = tail;
head.prev = null;
tail.prev = head;
tail.next = null;
map = new HashMap<>();
this.capacity = capacity;
this.size = 0;
}
public int get(int key) {
if (!map.containsKey(key)) {
return -1;
}
Node node = map.get(key);
deleteNode(node);
insertToFront(node);
return node.val;
}
public void put(int key, int val) {
if (map.containsKey(key)) {
Node node = map.get(key);
node.val = val;
deleteNode(node);
insertToFront(node);
} else {
Node node = new Node(key, val);
map.put(key, node);
if (size >= capacity) {
map.remove(tail.prev.key); // 一定要先 remove map 再 deleteNode 否则会报错!!
deleteNode(tail.prev);
insertToFront(node);
} else {
insertToFront(node);
size++;
}
}
}
private void deleteNode(Node node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
private void insertToFront(Node node) {
Node next = head.next;
head.next = node;
node.prev = head;
node.next = next;
next.prev = node;
}
}
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache obj = new LRUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/