题解 | #设计LRU缓存结构#
设计LRU缓存结构
http://www.nowcoder.com/practice/e3769a5f49894d49b871c09cadd13a61
LRU-自建双向链表
使用LinkedHashMap的同学可以歇歇了,面试你用LinkedHashMap试试:)
所以这里提供自建方案,学习自lc
import java.util.*;
public class Solution {
// 链表节点,用于存放数据,为HashMap提供顺序
private class Node {
int key;
int value;
Node pre;
Node next;
public Node(){}
public Node(int key, int value) {
this.key = key;
this.value = value;
}
}
Node head; // 头节点
Node tail; // 尾节点
int size; // 容量
int capacity; // 容量上限
Map<Integer, Node> cache; // 方便查找节点,实现O(1)查找时间复杂度
/**
* lru design
* @param operators int整型二维数组 the ops
* @param k int整型 the k
* @return int整型一维数组
*/
public int[] LRU (int[][] operators, int k) {
// write code here
init(k);
List<Integer> res = new ArrayList<>();
for (int[] o : operators) {
if (o[0] == 1) {
set(o[1], o[2]);
} else {
res.add(get(o[1]));
}
}
return res.stream().mapToInt(Integer::intValue).toArray();
}
// 初始化LRU
private void init(int capacity) {
this.size = 0;
this.capacity = capacity;
cache = new HashMap<>();
head = new Node();
tail = new Node();
head.next = tail;
tail.pre = head;
}
// 查找节点
private int get(int key) {
Node node = cache.get(key);
if (node == null) return -1; // 不存在返回-1;
moveToHead(node); //存在则将节点移至链表头部
return node.value;
}
// 设置节点
private void set(int key, int value) {
Node node = cache.get(key);
if (node == null) { // 节点不存在,新建节点并插入链表头部和哈希表
node = new Node(key, value);
addToHead(node);
cache.put(key, node);
size++;
if (size > capacity) { // 容量超过容量上限,则移除链表尾部,并删除对应哈希表数据
cache.remove(tail.pre.key);
removeNode(tail.pre);
size--;
}
} else { // 节点已存在,则修改value,并将节点移至头部
node.value = value;
moveToHead(node);
}
}
// 将链表节点移至链表头部
private void moveToHead(Node node) {
removeNode(node);
addToHead(node);
}
// 将节点移除
private void removeNode(Node node) {
node.pre.next = node.next;
node.next.pre = node.pre;
}
// 将节点添加至链表头部
private void addToHead(Node node) {
node.next = head.next;
node.pre = head;
node.next.pre = node;
node.pre.next = node;
}
}