Leetcode: LRU Cache 解題報告


LRU Cache

 Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations:  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 }
View Code

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 }
View Code

 

請移步至主頁君的GITHUB代碼:

https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/hash/LRUCache.java

https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/hash/LRUCache2.java

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM