[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  */

猜你喜欢

转载自www.cnblogs.com/liuliu5151/p/9814322.html