思路:
自定义一个链表+哈希表(哈希不需要自己写)
代码:
class LRUCache {
//自定义一个链表
class DlinkedNode{
int key;
int value;
DlinkedNode pre;
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;
private DlinkedNode head,tail;
public LRUCache(int capacity) {
//初始化
this.capacity=capacity;
this.size=0;
//伪头部和伪尾部
head=new DlinkedNode();
tail=new DlinkedNode();
head.next=tail;
tail.pre=head;
}
public int get(int key) {
DlinkedNode node=cache.get(key);
if(node==null){
return -1;
}
//如果key存在,移到头部
moveToHead(node);
return node.value;
}
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{
//存在节点,则覆盖value即可
node.value=value;
//再将赋值过的node重新加到链表头
moveToHead(node);
}
}
private void moveToHead(DlinkedNode node){
removeNode(node);
addToHead(node);
}
private void addToHead(DlinkedNode node){
//node节点里只有pre和next,没有tail,所以不用设置tail
node.pre=head;
node.next=head.next;
head.next.pre=node;
head.next=node;
}
private void removeNode(DlinkedNode node){
node.pre.next=node.next;
node.next.pre=node.pre;
}
private DlinkedNode removeTail(){
DlinkedNode res=tail.pre;
removeNode(res);
return res;
}
}
分解:
1)自定义双向链表+哈希:
头部是最近使用的,尾部是最久未使用的,如果要删除节点,就删除尾部的
设置2个指针,伪头部和伪尾部
复杂度分析:
时间复杂度:O(1) get和put都是O(1)的时间复杂度
空间复杂度:O(capacity)map里只存储Capacity容量的数据