LRU算法
解析
题目
使用LinkedHashMap
class LRUCache { int cap; LinkedHashMap<Integer, Integer> cache = new LinkedHashMap<>(); public LRUCache(int capacity) { this.cap = capacity; } public int get(int key) { if (!cache.containsKey(key)) { return -1; } // 将 key 变为最近使用 makeRecently(key); return cache.get(key); } public void put(int key, int val) { if (cache.containsKey(key)) { // 修改 key 的值 cache.put(key, val); // 将 key 变为最近使用 makeRecently(key); return; } if (cache.size() >= this.cap) { // 链表头部就是最久未使用的 key int oldestKey = cache.keySet().iterator().next(); cache.remove(oldestKey); } // 将新的 key 添加链表尾部 cache.put(key, val); } private void makeRecently(int key) { int val = cache.get(key); // 删除 key,重新插入到队尾 cache.remove(key); cache.put(key, val); }}
不使用LinkedHashMap
class LRUCache { HashMap<Integer,Node> cache; Node head; Node tail; int capacity; int size; public LRUCache(int capacity) { cache=new HashMap<>(); this.capacity=capacity; this.size=0; head=new Node(); tail=new Node(); head.next=tail; tail.pre=head; } public int get(int key) { if(cache.containsKey(key)){ Node node=cache.get(key); moveToHead(node); return node.val; }else{ return -1; } } public void put(int key, int value) { if(cache.containsKey(key)){ Node node=cache.get(key); node.val=value; moveToHead(node); }else{ Node cur=new Node(key,value); addNode(cur); } } private void addNode(Node node){ if(size==capacity){ deleteOldestNode(); } node.next=head.next; node.next.pre=node; node.pre=head; node.pre.next=node; size++; cache.put(node.key,node); } private void deleteOldestNode(){ Node node=tail.pre; tail.pre=node.pre; tail.pre.next=tail; cache.remove(node.key); size--; } private void moveToHead(Node node){ node.pre.next=node.next; node.next.pre=node.pre; node.next=head.next; node.next.pre=node; node.pre=head; head.next=node; } public class Node{ int key; int val; Node pre; Node next; public Node(){} public Node(int _key,int _val){ this.key=_key; this.val=_val; } }}/** * 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); */
LFU算法
解析
题目
public class LFUCache { HashMap<Integer,Integer> keyToVal=new HashMap<>(); HashMap<Integer,Integer> keyToFreq=new HashMap<>(); HashMap<Integer, LinkedHashSet<Integer>> freqToKeys=new HashMap<>(); int minFreq; int capacity; public LFUCache(int capacity) { this.capacity=capacity; this.minFreq=0; } public int get(int key) { if(!keyToVal.containsKey(key)) return -1; increaseFreq(key); return keyToVal.get(key); } public void put(int key, int value) { if(this.capacity<=0) return; if(keyToVal.containsKey(key)){ keyToVal.put(key,value); increaseFreq(key); }else{ if(this.capacity==keyToVal.size()) deleteKey(); keyToVal.put(key,value); keyToFreq.put(key,1); freqToKeys.putIfAbsent(1,new LinkedHashSet<>()); freqToKeys.get(1).add(key); this.minFreq=1; } } private void increaseFreq(int key){ int freq=keyToFreq.get(key); keyToFreq.put(key,freq+1); // 将 key 加入 freq + 1 对应的列表中 freqToKeys.putIfAbsent(freq+1,new LinkedHashSet<>()); freqToKeys.get(freq+1).add(key); // 将 key 从 freq 对应的列表中删除 LinkedHashSet<Integer> keySet=freqToKeys.get(freq); keySet.remove(key); // 如果 freq 对应的列表空了,移除这个 freq if(keySet.isEmpty()){ freqToKeys.remove(freq); // 如果这个 freq 恰好是 minFreq,更新 minFreq if(freq==minFreq) minFreq++; } } private void deleteKey(){ // freq 最小的 key 列表 LinkedHashSet<Integer> keySet=freqToKeys.get(minFreq); // 其中最先被插入的那个 key 就是该被淘汰的 key int deletedKey=keySet.iterator().next(); keySet.remove(deletedKey); if(keySet.isEmpty()) freqToKeys.remove(minFreq); //在这里不需要像increaseFreq函数里面那样去更新minFreq,因为只有在插入新值的时候,会执行delete //而插入新缓存后,put函数会更新minFreq为1 keyToVal.remove(deletedKey); keyToFreq.remove(deletedKey); }}
最大频率栈
解析
题目
public class FreqStack { int maxFreq; HashMap<Integer, Integer> valToFreq = new HashMap<>(); HashMap<Integer, Stack<Integer>> freqToVals = new HashMap<>(); public FreqStack() { this.maxFreq = 0; } public void push(int val) { int freq = valToFreq.getOrDefault(val, 0)+1; valToFreq.put(val, freq); freqToVals.putIfAbsent(freq,new Stack<>()); freqToVals.get(freq).push(val); maxFreq=Math.max(maxFreq,freq); } public int pop() { Stack<Integer> stack=freqToVals.get(maxFreq); int res=stack.pop(); int freq=valToFreq.get(res)-1; valToFreq.put(res,freq); if(stack.isEmpty()) maxFreq--; return res; }}