LRU (最近最少使用)
LeetCode 146
一定要按顺序:
1.准备数据结构:双向链表+map (双向链表存数据,map查是否存在)
2.准备LRU主体类
3.准备LRU主体类方法:从put开始想,把put方法分为几个小方法,依次实现
//双向链表
class DLinkedNode{
//键值对数据
int key;
int value;
//pre和next
DLinkedNode pre;
DLinkedNode next;
//构造方法
DLinkedNode(){}
DLinkedNode(int key,int value){
this.key = key;
this.value = value;
}
}
//LRU主体类
class LRUCache {
//map
Map<Integer,DLinkedNode> cache;
//当前容量
int size;
//最大容量
int capacity;
//头尾结点
DLinkedNode head;
DLinkedNode tail;
//构造方法,每个属性都初始化
public LRUCache(int capacity) {
cache = new HashMap<>();
this.size = 0;
this.capacity = capacity;
head = new DLinkedNode();
tail = new DLinkedNode();
head.next = tail;
tail.pre = head;
}
//get()方法
public int get(int key) {
//先用map查查存不存在
DLinkedNode node = cache.get(key);
//不存在则取不到,返回-1
if (node==null){
return -1;
}else{
//存在则将这个节点放到第一位,引入第一个方法moveToHead()
moveToHead(node);
return node.value;
}
}
//put()方法
public void put(int key, int value) {
//一样先查存不存在这个节点
DLinkedNode node = cache.get(key);
//存在,则将value覆盖原来的value,并且放置到第一位moveToHead()
if (node!=null){
node.value = value;
moveToHead(node);
}
}else{
//不存在,则新建一个结点,并且放置到第一位addToHead()
node = new DLinkedNode(key, value);
addToHead(node);
//记得更新属性
cache.put(key,node);
size++;
//容量判断,如果超容量了,则把最后一个结点去掉,引入removeTail()
if (size>capacity){
cache.remove(tail.pre.key);
removeTail();
//记得更新属性
size--;
}
}
//removeNode(),直接将我的前置节点的后置节点设为我的后置节点,将我的后置节点的前置节点设为我的前置节点
void removeNode(DLinkedNode node){
node.pre.next = node.next;
node.next.pre = node.pre;
}
//addToHead(),与Head和原来的第一位节点交互
void addToHead(DLinkedNode node){
node.next = head.next;
head.next.pre = node;
head.next = node;
node.pre = head;
}
//moveToHead方法可以分为两步:1.移除原节点removeNode() 2.将节点放到第一位addToHead()
void moveToHead(DLinkedNode node){
removeNode(node);
addToHead(node);
}
//removeTail() 利用removeNode()去掉tail.pre即可
void removeTail(){
removeNode(tail.pre);
}
}
/**
* 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);
*/