LeetCode 146. LRU Cache

原题链接在这里:https://leetcode.com/problems/lru-cache/

题目:

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?

Example:

LRUCache cache = new LRUCache( 2 /* capacity */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // returns 1
cache.put(3, 3);    // evicts key 2
cache.get(2);       // returns -1 (not found)
cache.put(4, 4);    // evicts key 1
cache.get(1);       // returns -1 (not found)
cache.get(3);       // returns 3
cache.get(4);       // returns 4

题解:

可以通过HashMap 和 Double LinkedList来完成。每个key, value用一个Node 来储存,按照添加顺序一个一个放在list 的head后面。同时把<key, node>放在HashMap中。

get时看HashMap中是否有这个key, 有的话就找到对应的node, 在node里取出对应的value. 同时更新该node 在list中的位置。

set时分三种情况:1. 看HashMap中是否有这个key, 有的话说明本来就有这个key对应的node, 只需要把原有node的value更改并且更新该node 在list中位置即可。

2. HashMap中没有这个key, 同时HashMap的size未达到capacity, 那么新建一个node, 加入HashMap 和 list中即可。

3. HashMap中没有这个key, 同时HashMap的size已经等于capacity, 多加就要溢出,所以按照2中完成添加后要从HashMap 和 list中都去掉最老的node.

Time Complexity: get, O(1). put O(1).

Space: O(n).

AC Java:

 1 class Node{
 2     int key;
 3     int val;
 4     Node prev;
 5     Node next;
 6     public Node(int key, int val){
 7         this.key = key;
 8         this.val = val;
 9     }
10 }
11 
12 class LRUCache {
13     Node head;
14     Node tail;
15     Map<Integer, Node> hm;
16     int capacity;    
17 
18     public LRUCache(int capacity) {
19         head = new Node(-1, -1);
20         tail = new Node(1, 1);
21         head.next = tail;
22         tail.prev = head;
23         this.capacity = capacity;
24         hm = new HashMap<>();
25     }
26     
27     public int get(int key) {
28         if(!hm.containsKey(key)){
29             return -1;
30         }
31 
32         Node target = hm.get(key);
33         putToHead(target);
34         return target.val;
35     }
36     
37     public void put(int key, int value) {
38         if(hm.containsKey(key)){
39             Node cur = hm.get(key);
40             cur.val = value;
41             putToHead(cur);
42             return;
43         }
44 
45         if(hm.size() >= capacity){
46             int lastKey = removeOldest();
47             hm.remove(lastKey);
48         }
49 
50         Node addedNode = new Node(key, value);
51         hm.put(key, addedNode);
52         putToHead(addedNode);
53     }
54 
55     private void putToHead(Node cur){
56         if(cur.prev != null && cur.next != null){
57             cur.prev.next = cur.next;
58             cur.next.prev = cur.prev;
59         }
60 
61         cur.next = head.next;
62         cur.prev = head;
63         head.next.prev = cur;
64         head.next = cur;
65     }
66 
67     private int removeOldest(){
68         Node lastNode = tail.prev;
69         lastNode.prev.next = lastNode.next;
70         lastNode.next.prev = lastNode.prev;
71         return lastNode.key;
72     }
73 }
74 
75 /**
76  * Your LRUCache object will be instantiated and called as such:
77  * LRUCache obj = new LRUCache(capacity);
78  * int param_1 = obj.get(key);
79  * obj.put(key,value);
80  */

另一种方法是用LinkedHashMap, 这种数据结构本身已经把HashMap按照添加顺序放好了。

可以参见这个网页:http://www.tutorialspoint.com/java/java_linkedhashmap_class.htm 

所以实现起来很简洁,get时需要更新位置,更新位置是通过删掉旧的,复制一下加回去。

set时参照上面的三种情况即可。

AC Java:

 1 import java.util.LinkedHashMap;
 2 public class LRUCache {
 3     LinkedHashMap<Integer, Integer> linkedHM;
 4     int capacity;
 5     public LRUCache(int capacity) {
 6         linkedHM = new LinkedHashMap<Integer, Integer>();
 7         this.capacity = capacity;
 8     }
 9     
10     public int get(int key) {
11         if(linkedHM.containsKey(key)){
12             int val = linkedHM.get(key);
13             linkedHM.remove(key);
14             linkedHM.put(key,val);
15             return val;
16         }
17         return -1;
18     }
19     
20     public void set(int key, int value) {
21         if(linkedHM.containsKey(key)){
22             linkedHM.remove(key);
23             linkedHM.put(key,value);
24         }else if(linkedHM.size() < capacity){
25             linkedHM.put(key,value);
26         }else{
27             int oldKey = linkedHM.keySet().iterator().next();
28             linkedHM.remove(oldKey);
29             linkedHM.put(key,value);
30         }
31     }
32 }

 

posted @ 2015-11-04 09:36  Dylan_Java_NYC  阅读(459)  评论(0编辑  收藏  举报