LRU Cache
get
and
set
.
get(key)
- Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.set(key, value)
- Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.
SOLUTION 1:
利用了JAVA 自帶的LinkedHashMap ,其實這相當於作弊了,面試官不太可能會過。但是我們仍然可以練習一下如何使用LinkedHashMap.
同學們可以參考一下它的官方文檔:
https://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashMap.html#LinkedHashMap(int)
1. OverRide removeEldestEntry 函數,在Size達到最大值最,刪除最長時間未訪問的節點。
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > capacity;
}
2. 在Get/ Set的時候,都更新節點,即刪除之,再添加之,這樣它會作為最新的節點加到雙向鏈表中。

1 package Algorithms.hash; 2 3 import java.util.LinkedHashMap; 4 import java.util.Map; 5 6 public class LRUCache2 { 7 public static void main(String[] strs) { 8 LRUCache2 lrc2 = new LRUCache2(2); 9 lrc2.set(1,3); 10 lrc2.set(2,2); 11 lrc2.set(1,4); 12 lrc2.set(4,2); 13 14 System.out.println(lrc2.get(1)); 15 } 16 17 LinkedHashMap<Integer, Integer> map; 18 int capacity; 19 20 public LRUCache2(final int capacity) { 21 // create a map. 22 map = new LinkedHashMap<Integer, Integer>(capacity) { 23 /** 24 * 25 */ 26 private static final long serialVersionUID = 1L; 27 28 protected boolean removeEldestEntry(Map.Entry eldest) { 29 return size() > capacity; 30 } 31 }; 32 this.capacity = capacity; 33 } 34 35 public int get(int key) { 36 Integer ret = map.get(key); 37 if (ret == null) { 38 return -1; 39 } else { 40 map.remove(key); 41 map.put(key, ret); 42 } 43 44 return ret; 45 } 46 47 public void set(int key, int value) { 48 map.remove(key); 49 map.put(key, value); 50 } 51 }
SOLUTION 2:
使用 HashMap+ 雙向鏈表實現:
1. 如果需要移除老的節點,我們從頭節點移除。
2. 如果某個節點被訪問(SET/GET),將其移除並掛在雙向鏈表的結尾。
3. 鏈表滿了后,我們刪除頭節點。
4. 最近訪問的節點在鏈尾。最久被訪問的節點在鏈頭。

1 package Algorithms.hash; 2 3 import java.util.HashMap; 4 5 public class LRUCache { 6 private class DLink { 7 DLink pre; 8 DLink next; 9 int val; 10 int key; 11 DLink(int key, int val) { 12 this.val = val; 13 this.key = key; 14 pre = null; 15 next = null; 16 } 17 } 18 19 HashMap<Integer, DLink> map; 20 21 DLink head; 22 DLink tail; 23 24 int capacity; 25 26 public void removeFist() { 27 removeNode(head.next); 28 } 29 30 public void removeNode(DLink node) { 31 node.pre.next = node.next; 32 node.next.pre = node.pre; 33 } 34 35 // add a node to the tail. 36 public void addToTail(DLink node) { 37 tail.pre.next = node; 38 39 node.pre = tail.pre; 40 node.next = tail; 41 42 tail.pre = node; 43 } 44 45 public LRUCache(int capacity) { 46 map = new HashMap<Integer, DLink>(); 47 48 // two dummy nodes. In that case, we can deal with them more conviencely. 49 head = new DLink(-1, -1); 50 tail = new DLink(-1, -1); 51 head.next = tail; 52 tail.pre = head; 53 54 this.capacity = capacity; 55 } 56 57 public int get(int key) { 58 if (map.get(key) == null) { 59 return -1; 60 } 61 62 // update the node. 63 DLink node = map.get(key); 64 removeNode(node); 65 addToTail(node); 66 67 return node.val; 68 } 69 70 public void set(int key, int value) { 71 DLink node = map.get(key); 72 if (node == null) { 73 // create a node and add the key-node pair into the map. 74 node = new DLink(key, value); 75 map.put(key, node); 76 } else { 77 // update the value of the node. 78 node.val = value; 79 removeNode(node); 80 } 81 82 addToTail(node); 83 84 // if the LRU is full, just remove a node. 85 if (map.size() > capacity) { 86 map.remove(head.next.key); 87 removeFist(); 88 } 89 } 90 }
請移步至主頁君的GITHUB代碼:
https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/hash/LRUCache.java
https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/hash/LRUCache2.java