https://leetcode-cn.com/problems/lru-cache/
这个题在Java可以偷鸡,直接用LinkedHashMap可以直接秒杀
import java.util.LinkedHashMap; import java.util.Map; class LRUCache { private LinkedHashMap lru; public LRUCache(int capacity) { lru = new LinkedHashMap(capacity,0.75f,true){ @Override protected boolean removeEldestEntry(Map.Entry eldest) { return lru.size() > capacity; } }; } public int get(int key) { if(lru.containsKey(key)) { return (int) lru.get(key); }else { return -1; } } public void put(int key, int value) { lru.put(key,value); } } /** * 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); */
但是当不用这个Map的时候,我们就要自己手写了。其实LinkedHashMap也是通过一个双向链表来维护了它的插入顺序,我们也可以照猫画虎做一下。
import java.util.HashMap;
public class LRUCache2 { /** * 使用一个双向链表来维护这个map的插入顺序,map的k为输入的key,v为双向链表中的节点。 */ public static class Node { int key; int val; Node next; Node prev; public Node(int key, int val) { this.key = key; this.val = val; } } private HashMap<Integer,Node> lru; private int size; private Node head; private Node tail; public LRUCache2(int capacity) { lru = new HashMap<>(); size = capacity; } public int get(int key) { Node temp = lru.get(key); //如果没有这个key对应的值,说明不存在,返回-1 if(temp == null){ return -1; }else { //说明存在,将它在双向链表的位置插入到最前面。 int res = temp.val; remove(temp); add(temp); return res; } } public void put(int key, int value) { Node temp = lru.get(key); //检查是否存在,如果存在就更新它的值,然后将它从双向链表中放到队头位置。 if(temp != null){ temp.val = value; remove(temp); add(temp); }else { temp = new Node(key,value); //如果已经溢出了,删除队尾的元素 if (lru.size() >= size) { lru.remove(tail.key); remove(tail); } add(temp); lru.put(key,temp); } } /** * 使用头插法,维护双向链表 * @param node */ private void add(Node node){ if(head == null){ head = tail = node; }else { node.next = head; head.prev = node; head = node; } } /** * 移除分三种情况,队列本身只有一个元素,移除的元素在队头、队尾、对中 * @param node */ private void remove(Node node){ if(head == tail){ head = tail = null; }else { if(head == node){ head = head.next; head.prev = null; node.next = null; }else if(node == tail){ tail = tail.prev; tail.next = null; node.prev = null; }else { node.prev.next = node.next; node.next.prev = node.prev; node.prev = null; node.next = null; } } } }
双向链表只是拿来维护这个数据的插入顺序,而map中的KV分别是key和对应的结点,结点内含有key和value两个属性。
想这个对应关系真的挺烦的,一开始是直接用LinkedList去做,发现怎么样都没办法将它们两者的关系处理好,只好自己造轮子了