1. 程式人生 > >[leetcode]146. LRU CacheLRU快取

[leetcode]146. LRU CacheLRU快取

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.

get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
put(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.

Follow up:
Could you do both operations in O(1) time complexity?

 

思路

使用HashMap + doubly LinkedList

 

 

HashMap儲存每個節點的地址,可以基本保證在O(1)時間內查詢節點
雙向連結串列能後在O(1)時間內新增和刪除節點,單鏈表則不行

具體實現細節:
越靠近連結串列頭部,表示節點上次訪問距離現在時間最短,尾部的節點表示最近訪問最少
訪問節點時,如果節點存在,把該節點交換到連結串列頭部,同時更新hash表中該節點的地址
插入節點時,如果cache的size達到了上限capacity,則刪除尾部節點,同時要在hash表中刪除對應的項;新節點插入連結串列頭部

 

思考:

1. why not using java.util.LinkedinList? 

因為java自帶的linkedlist中,刪除操作是從頭到尾scan特定值再刪除,時間為O(n)。但題目要求O(1)。

2. why not using java.util.LinkedHashMap?
這題說白了,就是考察java自帶的LinkedHashMap是怎麼實現的,我們當然不能。

 

程式碼

 1 public class LRUCache {
 2     private int capacity;
 3     private final
HashMap<Integer, Node> map; 4 private Node head; 5 private Node end; 6 7 public LRUCache(int capacity) { 8 this.capacity = capacity; 9 map = new HashMap<>(); 10 } 11 12 public int get(int key) { 13 // no key exists 14 if(!map.containsKey(key)) return -1; 15 // key exists, then move it to the front 16 Node n = map.get(key); 17 remove(n); 18 setHead(n); 19 return n.value; 20 21 } 22 23 public void put(int key, int value) { 24 // key exits 25 if (map.containsKey(key)){ 26 // update the value 27 Node old = map.get(key); 28 old.value = value; 29 // move it to the front 30 remove(old); 31 setHead(old); 32 } 33 // no key exists 34 else { 35 Node created = new Node(key, value); 36 // reach the capacity, move the oldest item 37 if (map.size() >= capacity){ 38 map.remove(end.key); 39 remove(end); 40 setHead(created); 41 } 42 // insert the entry into list and update mapping 43 else { 44 setHead(created); 45 } 46 map.put(key, created); 47 } 48 } 49 50 private void remove(Node n){ 51 if (n.prev !=null) { 52 n.prev.next = n.next; 53 } else { 54 head = n.next; 55 } 56 if (n.next != null) { 57 n.next.prev = n.prev; 58 } else { 59 end = n.prev; 60 } 61 62 } 63 64 private void setHead(Node n){ 65 n.next = head; 66 n.prev = null; 67 if (head!=null ) head.prev = n; 68 69 head = n; 70 71 if(end == null) end = head; 72 } 73 74 // doubly linked list 75 class Node { 76 int key; 77 int value; 78 Node prev; 79 Node next; 80 81 public Node(int key, int value) { 82 this.key = key; 83 this.value = value; 84 } 85 } 86 } 87 88 /** 89 * Your LRUCache object will be instantiated and called as such: 90 * LRUCache obj = new LRUCache(capacity); 91 * int param_1 = obj.get(key); 92 * obj.put(key,value); 93 */