Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations:
get and set.get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.set(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.
链表题系列的最后一道题,要求设计一种在操作系统中用到的LRU Cache,核心思路是使用HashMap和双向链表来实现节点的开始查找以及删除和插入。注意一些小细节不要形成环或者节点为null。
public class LRUCache {
public class CacheNode {
int key, val;
CacheNode prior, next;
public CacheNode(int key, int val) {
this.key = key;
this.val = val;
prior = null; next = null;
}
}
CacheNode head, tail;
int size, capacity;
HashMap<Integer, CacheNode> map; // fast look up for a specific node
public LRUCache(int capacity) {
head = new CacheNode(0, 0);
tail = head;
size = 0;
this.capacity = capacity;
map = new HashMap<Integer, CacheNode>();
}
public int get(int key) {
if(map.containsKey(key) == false) {
return -1;
}
else {
update(map.get(key));
return map.get(key).val;
}
}
public void set(int key, int value) {
if(map.containsKey(key) == true) {
CacheNode node = map.get(key);
node.val = value;
update(node);
map.put(key, node);
}
else {
CacheNode node = new CacheNode(key, value);
add(node);
map.put(key, node);
}
}
private void update(CacheNode node) { // put the node at the back of a list
if(node == tail) return; // be careful with corner case
node.prior.next = node.next;
node.next.prior = node.prior;
node.prior = tail;
tail.next = node;
node.next = null;
tail = node;
}
private void add(CacheNode node) {
if(size < capacity) {
tail.next = node;
node.prior = tail;
tail = node;
size++;
}
else {
if(head.next == null) return;
if(tail == head.next) tail = head; // be careful with corner case
map.remove(head.next.key); // remove the head of the list
head.next = head.next.next;
if(head.next != null) head.next.prior = head;
tail.next = node;
node.prior = tail;
tail = node;
}
}
}
没有评论:
发表评论