思路分析
LRU(最近最少使用)的设计策略重点在于维护固定格式的缓存,这里用双向链表来维护这些缓存数据,更准确的来说是利用哈希表和双向链表来完成这一设计,哈希表的作用是在O(1)的时间内完成查找,双端链表则是用来保持按使用频率排序的操作,这个题目我们需要理解的是,如果进行了插入和取出,那么就要对缓存的数据进行排序。
因为数据既有key又有value,那么肯定需要使用到HashMap,并且我们如果插入或者取出数据后都要排序,并且set和get的时间复杂度都要是O(1),那么必须使用双向链表来维持缓存数据,因为如果是单向的链表删除数据的时候无法做到O(1)时间复杂度。
class LRUCache {/*定义一个Node*/class Node{int key;int value;Node next;Node pre;public Node(int key, int value){this.key = key;this.value = value;}}//需要定义一个mapprivate HashMap<Integer,Node> map;//定义缓存容量private int capacity;//定义头结点private Node head;//定义尾结点private Node tail;public LRUCache(int capacity) {//对这个cache进行初始化map = new HashMap<>();this.capacity = capacity;head = null;tail = null;}public int get(int key) {Node node = map.get(key);if(node==null){return -1;}//重新排序if(node!=tail){if(node==head){head = head.next;}else{node.pre.next = node.next;node.next.pre = node.pre;}tail.next = node;node.pre = tail;node.next = null;tail = node;}return node.value;}public void put(int key, int value) {Node node = map.get(key);if(node!=null){node.value = value;//重新排序if(node!=tail){if(node==head){head = head.next;}else{node.pre.next = node.next;node.next.pre = node.pre;}tail.next = node;node.pre = tail;node.next = null;tail = node;}}else{Node newNode = new Node(key, value);if(capacity==0){Node temp = head;head = head.next;if(temp==tail){tail = null;}map.remove(temp.key);capacity++;}if(head==null&&tail==null){head = newNode;}else{tail.next = newNode;newNode.pre = tail;newNode.next = null;}tail = newNode;map.put(key,newNode);capacity--;}}}/*** 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);*/
