大厂面试官让我手写LRU缓存,还好提前抱了佛脚,春招有希望了_哔哩哔哩_bilibili
class LRUCache {
// 定义一个双向链表
static class Node {
Integer key;
Integer value;
public Node(Integer key, Integer value) {
this.key = key;
this.value = value;
}
Node pre;
Node next;
}
// 用来快速定位节点和记录节点数量
private HashMap<Integer, Node> map;
// 虚拟头节点
private Node dummyFirst;
// 虚拟尾节点
private Node dummyLast;
// LRU的容量
private int capacity;
/**
* 初始化方法
* @param capacity 指定缓存的容量
*/
public LRUCache(int capacity) {
map = new HashMap<>(capacity);
dummyFirst = new Node(-1, -1);
dummyLast = new Node(-1, -1);
// 建立虚拟头和虚拟尾节点的关系
dummyFirst.next = dummyLast;
dummyLast.pre = dummyFirst;
this.capacity = capacity;
}
/**
* 从缓存中获取数据
* @param key 缓存的键
* @return 缓存的值
*/
public int get(int key) {
// 如果map中没有这个key,证明没有命中缓存,直接返回-1即可
if (!map.containsKey(key)) {
return -1;
}
Node target = map.get(key);
// 将命中缓存的节点移到链表的最末尾(虚拟尾节点前面)
moveToTail(target, false);
return target.value;
}
/**
* 向缓存中写入数据
* @param key 写入的键
* @param value 写入的值
*/
public void put(int key, int value) {
// 如果这个map存在的话,
只需要把这个节点移到链表的最末尾(虚拟尾节点前面),并修改链表的值即可
if (map.containsKey(key)) {
moveToTail(map.get(key), false);
map.get(key).value = value;
return;
}
// 如果map不存在的话,需要在map和链表的最末尾(虚拟尾节点前面)新增这个节点,
并且检查现在缓存超没超容量,如果超了的话需要删除链表的最前面的节点(虚拟头节点的后面)
Node node = new Node(key, value);
map.put(key, node);
moveToTail(node, true);
while (map.size() > capacity) {
map.remove(dummyFirst.next.key);
dummyFirst.next = dummyFirst.next.next;
dummyFirst.next.pre = dummyFirst;
}
}
/**
* 将节点移动至链表的末尾,假末尾节点前面
*/
private void moveToTail(Node node, boolean insert) {
// 如果不是新增,此操作为将node.next移动到左边,
//我们要维护原节点的pre和next节点的next和pre引用
if (!insert) {
node.pre.next = node.next;
node.next.pre = node.pre;
}
// 将节点移动到链表的最末尾(虚拟尾节点前面)
node.next = dummyLast;
node.pre = dummyLast.pre;
dummyLast.pre = node;
node.pre.next = node;
}
}
双向链表的插入:
int a=12;
int b;
int *p;
int **ptr;
p=&a;//&a的结果是一个指针,类型是int*,指向的类型是int,指向的地址是a的地址。
*p=24;//*p的结果,在这里它的类型是int,它所占用的地址是p所指向的地址,显然,*p就是变量a。
ptr=&p;//&p的结果是个指针,该指针的类型是p的类型加个*,在这里是int**。该指针所指向的类型是p的类型,这里是int*。该指针所指向的地址就是指针p自己的地址。
*ptr=&b;//*ptr是个指针,&b的结果也是个指针,且这两个指针的类型和所指向的类型是一样的,所以?amp;b来给*ptr赋值就是毫无问题的了。
**ptr=34;//*ptr的结果是ptr所指向的东西,在这里是一个指针,对这个指针再做一次*运算,结果就是一个int类型的变量。