LRU缓存机制-算法
其底层实现的用map管理的双向链表,在链表的头部存放最近被访问的,尾部自然就是最近最久未被访问的节点。
其中需要保存的有size、capacity、head、tail、map成员属性
方法有get和put,
初始化的时候,需要设置参数大小,如果不设置的话,默认为10;
get方法,需要判断map中是否存在,如果存在直接返回,不存在放回-1;
put方法,需要判断map中是否存在,如果存在则修改当前key的value值,如果不存在,新建一个node,加入到map中,然后size ++;判断是否超出capacity,超出的话,需要移除链表尾元素,然后移除map的尾元素。
在使用get方法,需要将我们访问到元素加入到链表头部,并移除原先的关系。
在使用put方法,如果不存在,需要将我们访问到元素加入到链表头部且size大于capacity时,需要删除链表尾部元素,如果存在的话,将元素加入到链表头部,并移除原先的关系。
package com.lhb.offer; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; /** * @author lhb * @date 2022/3/14 */ public class Offer_146 { class Node{ int key; int val; Node prev; Node next; public Node(int key, int val) { this.val = val; this.key = key; } public Node() { } } Map<Integer, Node> map; int capacity = 0; int size; Node head, tail; public Offer_146() { this(10); } public Offer_146(int capacity) { this.size = 0; this.capacity = capacity; head = new Node(); tail = new Node(); map = new HashMap<>(); head.next = tail; tail.prev = head; } int get(int key) { Node node = map.get(key); if (node == null) { return -1; } removeNodeToHead(node); return node.val; } void put(int key, int val){ Node node = map.get(key); if (node == null) { Node newNode = new Node(key, val); moveToHead(newNode); ++size; if (size > capacity) { Node tail = removeTail(); map.remove(tail.key); --size; } } else { node.val = val; moveToHead(node); } node.next = head.next; head.next = node; size ++; } void removeNodeToHead(Node node) { removeNode(node); moveToHead(node); } void moveToHead(Node node) { node.next = head.next; head.next =node; } void removeNode(Node node) { node.prev.next = node.next; node.next.prev = node.prev; } Node removeTail() { Node temp = tail.prev; removeNode(temp); return temp; } public static void main(String[] args) { } }