今天写这道题,背过八股文的都应该知道LRU算法缓存的基本原理,在 Java
语言中,同样有类似的数据结构 LinkedHashMap,
本题我们采用自己创建哈希表+双链表的形式简单实现一下
对于get操作:通过cache.get(key)获取,如果不存在则直接返回-1,否则返回对于key的value并把该结点移动到链表头部
对于put操作:通过cache.get(key)获取,如果存在则直接替换该结点的value并把该结点移动到链表头部,否则创建新的结点,把它put到chache中,然后添加到链表头部并且size++,最后判断size是否大于capacity,如果大于则需要移除链表尾部结点,并且需要移除cache中对应的结点,最后size--
代码如下
class LRUCache {
// 双链表
class DLinkedNode {
int key;
int value;
DLinkedNode prev;
DLinkedNode next;
public DLinkedNode() {
}
public DLinkedNode(int _key, int _value) {
key = _key;
value = _value;
}
}
// 创建哈希表
private Map<Integer, DLinkedNode> cache = new HashMap<>();
// 哈希表当前结点个数
private int size;
// 最大结点个数,不能超过此阈值,否则需要进行移除链表尾结点操作
private int capacity;
// 双链表伪头部和伪尾部
DLinkedNode head, tail;
// 传入一个int型数字构建一个LRUCache对象
public LRUCache(int capacity) {
this.size = 0;
this.capacity = capacity;
head = new DLinkedNode();
tail = new DLinkedNode();
head.next = tail;
tail.prev = head;
}
// get操作
public int get(int key) {
DLinkedNode node = cache.get(key);
if (node == null) {
return -1;
}
moveToHead(node);
return node.value;
}
public void moveToHead(DLinkedNode node) {
removeNode(node);
addToHead(node);
}
public void removeNode(DLinkedNode node) {
node.next.prev = node.prev;
node.prev.next = node.next;
}
public void addToHead(DLinkedNode node) {
node.prev = head;
node.next = head.next;
head.next.prev = node;
head.next = node;
}
// put操作
public void put(int key, int value) {
DLinkedNode node = cache.get(key);
if (node == null) {
DLinkedNode newNode = new DLinkedNode(key, value);
cache.put(key, newNode);
addToHead(newNode);
size++;
if (size > capacity) {
DLinkedNode tail = removeTail();
cache.remove(tail.key);
size--;
}
} else {
node.value = value;
moveToHead(node);
}
}
private DLinkedNode removeTail() {
DLinkedNode res = tail.prev;
removeNode(res);
return res;
}
}